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 ec84baa9ed60d1161117164700bfa7e8d2c38e46..271ee97b99d22e51b74496ab0eebaf935ad0e9fc 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
@@ -47,6 +47,7 @@ import com.oracle.truffle.r.runtime.RContext.ConsoleHandler;
 import com.oracle.truffle.r.runtime.data.*;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile;
+import com.oracle.truffle.r.runtime.data.model.*;
 import com.oracle.truffle.r.runtime.env.*;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.ffi.*;
@@ -364,6 +365,7 @@ public final class REngine implements RContext.Engine {
             } catch (ControlFlowException cfe) {
                 throw RError.error(RError.Message.NO_LOOP_FOR_BREAK_NEXT);
             }
+            assert !FastROptions.CheckResultCompleteness.getValue() || checkResult(result);
             if (printResult) {
                 printResult(result);
             }
@@ -382,6 +384,13 @@ public final class REngine implements RContext.Engine {
         return result;
     }
 
+    private static boolean checkResult(Object result) {
+        if (result instanceof RAbstractVector && ((RAbstractVector) result).isComplete()) {
+            assert ((RAbstractVector) result).checkCompleteness() : "vector: " + result + " is not complete, but isComplete flag is true";
+        }
+        return true;
+    }
+
     private static final PromiseProfile globalPromiseProfile = new PromiseProfile();
 
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java
index 48503680bc4be5267a436f767ac0866e9a3b02bc..ea99c9c48723e574c9df4b35f3df07c1211e9bc5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java
@@ -63,10 +63,12 @@ public abstract class ColSums extends RBuiltinNode {
         boolean isComplete = true;
         final boolean rna = removeNA.profile(naRm == RRuntime.LOGICAL_TRUE);
         na.enable(x);
+        double[] data = x.getDataWithoutCopying();
+        int pos = 0;
         nextCol: for (int c = 0; c < colNum; ++c) {
             double sum = 0;
             for (int i = 0; i < rowNum; ++i) {
-                double el = x.getDataAt(c * rowNum + i);
+                double el = data[pos++];
                 if (rna) {
                     if (!na.check(el) && !Double.isNaN(el)) {
                         sum = add.op(sum, el);
@@ -74,11 +76,13 @@ public abstract class ColSums extends RBuiltinNode {
                 } else {
                     if (na.check(el)) {
                         result[c] = RRuntime.DOUBLE_NA;
+                        pos += rowNum - i - 1;
                         continue nextCol;
                     }
                     if (Double.isNaN(el)) {
                         result[c] = Double.NaN;
                         isComplete = false;
+                        pos += rowNum - i - 1;
                         continue nextCol;
                     }
                     sum = add.op(sum, el);
@@ -95,10 +99,12 @@ public abstract class ColSums extends RBuiltinNode {
         double[] result = new double[colNum];
         final boolean rna = removeNA.profile(naRm == RRuntime.LOGICAL_TRUE);
         na.enable(x);
+        byte[] data = x.getDataWithoutCopying();
+        int pos = 0;
         nextCol: for (int c = 0; c < colNum; ++c) {
             double sum = 0;
             for (int i = 0; i < rowNum; ++i) {
-                byte el = x.getDataAt(c * rowNum + i);
+                byte el = data[pos++];
                 if (rna) {
                     if (!na.check(el)) {
                         sum = add.op(sum, el);
@@ -106,6 +112,7 @@ public abstract class ColSums extends RBuiltinNode {
                 } else {
                     if (na.check(el)) {
                         result[c] = RRuntime.DOUBLE_NA;
+                        pos += rowNum - i - 1;
                         continue nextCol;
                     }
                     sum = add.op(sum, el);
@@ -122,10 +129,12 @@ public abstract class ColSums extends RBuiltinNode {
         double[] result = new double[colNum];
         final boolean rna = removeNA.profile(naRm == RRuntime.LOGICAL_TRUE);
         na.enable(x);
+        int[] data = x.getDataWithoutCopying();
+        int pos = 0;
         nextCol: for (int c = 0; c < colNum; ++c) {
             double sum = 0;
             for (int i = 0; i < rowNum; ++i) {
-                int el = x.getDataAt(c * rowNum + i);
+                int el = data[pos++];
                 if (rna) {
                     if (!na.check(el)) {
                         sum = add.op(sum, el);
@@ -133,6 +142,7 @@ public abstract class ColSums extends RBuiltinNode {
                 } else {
                     if (na.check(el)) {
                         result[c] = RRuntime.DOUBLE_NA;
+                        pos += rowNum - i - 1;
                         continue nextCol;
                     }
                     sum = add.op(sum, el);
@@ -149,5 +159,4 @@ public abstract class ColSums extends RBuiltinNode {
         controlVisibility();
         throw RError.error(getEncapsulatingSourceSection(), RError.Message.X_NUMERIC);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDiag.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDiag.java
index 1eaa5b17eff11588dc2b2b99bc81272719d85b50..9db416a6efd4a91baaae1971763b4fd6ab7f01a3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDiag.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDiag.java
@@ -90,7 +90,7 @@ public abstract class UpdateDiag extends RInvisibleBuiltinNode {
         int nrow = resultVector.getDimensions()[0];
         int size = Math.min(nrow, resultVector.getDimensions()[1]);
         int pos = 0;
-        naCheck.enable(!resultVector.isComplete());
+        naCheck.enable(resultVector);
         for (int i = 0; i < size; i++) {
             resultVector.updateDataAt(pos, valueVector.getDataAt(i % valueVector.getLength()), naCheck);
             pos += nrow + 1;
@@ -110,7 +110,7 @@ public abstract class UpdateDiag extends RInvisibleBuiltinNode {
         int size = Math.min(resultVector.getDimensions()[0], resultVector.getDimensions()[1]);
         int nrow = resultVector.getDimensions()[0];
         int pos = 0;
-        naCheck.enable(!resultVector.isComplete());
+        naCheck.enable(resultVector);
         for (int i = 0; i < size; i++) {
             resultVector.updateDataAt(pos, valueVector.getDataAt(i % valueVector.getLength()), naCheck);
             pos += nrow + 1;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/ArrayPositionCast.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/ArrayPositionCast.java
index 6904958bc30fe97849d25f79d2d0768fdd266bd2..a9a70f2a664cbdb82df2582c83a0129092096996 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/ArrayPositionCast.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/ArrayPositionCast.java
@@ -659,7 +659,7 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
             int logicalVectorLength = operand.getLength();
             int logicalVectorInd = 0;
             int[] data = new int[resultLength];
-            naCheck.enable(!operand.isComplete());
+            naCheck.enable(operand);
             int timesSeenFalse = 0;
             int timesSeenNA = 0;
             int i = 0;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java
index 42cc3f0d73727ff0f766e5231a30dc66ca76f5c1..c39914478c57d7c429408e0d5dd6b0ac2215f5e8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java
@@ -368,7 +368,7 @@ public abstract class AccessArrayNode extends RNode {
             int accSrcDimensions = vector.getLength() / srcDimSize;
             int accDstDimensions = resLength / p.getLength();
 
-            elementNACheck.enable(!p.isComplete());
+            elementNACheck.enable(p);
             for (int i = 0; i < p.getLength(); i++) {
                 int dstArrayBase = accDstDimensions * i;
                 int pos = p.getDataAt(i);
@@ -1352,7 +1352,7 @@ public abstract class AccessArrayNode extends RNode {
             int accSrcDimensions = vector.getLength() / srcDimSize;
             int accDstDimensions = resLength / p.getLength();
 
-            elementNACheck.enable(!p.isComplete());
+            elementNACheck.enable(p);
             for (int i = 0; i < p.getLength(); i++) {
                 int dstArrayBase = accDstDimensions * i;
                 int pos = p.getDataAt(i);
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 ca31defef717cb4c7268e3c49f94a3b39e86a222..67602fb83ed29fc39cf02ccea30d332485c790b4 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
@@ -750,8 +750,8 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
         if (emptyVector.profile(length == 0)) {
             return RDataFactory.createEmptyDoubleVector();
         }
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
         double[] result = new double[length];
         for (int i = 0; i < length; ++i) {
             double leftValue = left.getDataAt(i);
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 40bec6926fa771ed92988b51ca2b2782a1a1ffd0..4ed662fbd44f94187b2f67b8686cc4d5ef46d775 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
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.nodes.unary.CastLogicalNode.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 import com.oracle.truffle.r.runtime.data.closures.*;
@@ -46,6 +47,8 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     private final NACheck leftNACheck = NACheck.create();
     private final NACheck rightNACheck = NACheck.create();
 
+    private final NAProfile resultNAProfile = NAProfile.create();
+
     public BinaryBooleanNode(BooleanOperationFactory factory) {
         this.factory = factory;
         this.logic = factory.create();
@@ -1483,44 +1486,58 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
 
     // int vector and scalar implementation
 
+    private RLogicalVector createResult(RAbstractVector left, byte[] result, boolean naResult) {
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
+        ret.copyNamesFrom(left);
+        return ret;
+    }
+
     private RLogicalVector performIntVectorOp(RAbstractIntVector left, double rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             int leftValue = left.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performIntVectorOp(RAbstractIntVector left, String rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             String leftValue = RRuntime.intToString(left.getDataAt(i), false);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performIntVectorOp(RAbstractIntVector left, RComplex rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             RComplex leftValue = RRuntime.int2complex(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
         RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
@@ -1533,41 +1550,49 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     private RLogicalVector performDoubleVectorOp(RAbstractDoubleVector left, double rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             double leftValue = left.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performDoubleVectorOp(RAbstractDoubleVector left, String rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             String leftValue = RRuntime.doubleToString(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performDoubleVectorOp(RAbstractDoubleVector left, RComplex rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             RComplex leftValue = RRuntime.double2complex(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
         RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
@@ -1580,26 +1605,32 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     private RLogicalVector performLogicalVectorOp(RAbstractLogicalVector left, double rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             byte leftValue = left.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performLogicalVectorOp(RAbstractLogicalVector left, String rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             String leftValue = RRuntime.logicalToString(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
         RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
@@ -1610,16 +1641,18 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     private RLogicalVector performLogicalVectorOp(RAbstractLogicalVector left, RComplex rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             RComplex leftValue = RRuntime.logical2complex(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     // string vector and scalar implementation
@@ -1627,16 +1660,18 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     private RLogicalVector performStringVectorOp(RAbstractStringVector left, String rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             String leftValue = left.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     // complex vector and scalar implementation
@@ -1644,76 +1679,86 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     private RLogicalVector performComplexVectorOp(RAbstractComplexVector left, RComplex rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             RComplex leftValue = left.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performComplexVectorOp(RAbstractComplexVector left, String rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             String leftValue = RRuntime.complexToString(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performRawVectorOp(RAbstractRawVector left, double rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             double leftValue = RRuntime.raw2double(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performRawVectorOp(RAbstractRawVector left, String rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             String leftValue = RRuntime.rawToString(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RLogicalVector performRawVectorOp(RAbstractRawVector left, RComplex rightValue, boolean reverse) {
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
+        leftNACheck.enable(left);
         rightNACheck.enable(rightValue);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             RComplex leftValue = RRuntime.raw2complex(left.getDataAt(i));
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : (!reverse ? logic.op(leftValue, rightValue) : logic.op(rightValue, leftValue));
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.getDimensions());
-        ret.copyNamesFrom(left);
-        return ret;
+        return createResult(left, result, naResult);
     }
 
     private RRawVector performRawVectorOp(RAbstractRawVector left, RRaw rightValue, boolean reverse) {
@@ -1735,15 +1780,20 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         assert areSameLength(left, right);
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             int leftValue = left.getDataAt(i);
             int rightValue = right.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue);
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.hasDimensions() ? left.getDimensions() : right.getDimensions());
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(),
+                        left.hasDimensions() ? left.getDimensions() : right.getDimensions());
         ret.copyNamesFrom(left.getNames() != null && left.getNames() != RNull.instance ? left : right);
         return ret;
     }
@@ -1754,21 +1804,25 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         int rightLength = right.getLength();
         int resultLength = Math.max(leftLength, rightLength);
         byte[] result = new byte[resultLength];
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
         int l = 0;
         int r = 0;
+        boolean naResult = false;
         for (int i = 0; i < resultLength; ++i, l = Utils.incMod(l, leftLength), r = Utils.incMod(r, rightLength)) {
             int leftValue = left.getDataAt(l);
             int rightValue = right.getDataAt(r);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue);
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
         boolean notMultiple = l != 0 || r != 0;
         if (notMultiple) {
             RError.warning(RError.Message.LENGTH_NOT_MULTI);
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA());
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA());
         ret.setDimensions(left.hasDimensions() ? left.getDimensions() : right.getDimensions(), this.getSourceSection());
         ret.copyNamesFrom(leftLength == resultLength ? left : right);
         return ret;
@@ -1780,15 +1834,20 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         assert areSameLength(left, right);
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             double leftValue = left.getDataAt(i);
             double rightValue = right.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue);
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.hasDimensions() ? left.getDimensions() : right.getDimensions());
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(),
+                        left.hasDimensions() ? left.getDimensions() : right.getDimensions());
         ret.copyNamesFrom(left.getNames() != null && left.getNames() != RNull.instance ? left : right);
         return ret;
     }
@@ -1799,21 +1858,25 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         int rightLength = right.getLength();
         int resultLength = Math.max(leftLength, rightLength);
         byte[] result = new byte[resultLength];
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
         int l = 0;
         int r = 0;
+        boolean naResult = false;
         for (int i = 0; i < resultLength; ++i, l = Utils.incMod(l, leftLength), r = Utils.incMod(r, rightLength)) {
             double leftValue = left.getDataAt(l);
             double rightValue = right.getDataAt(r);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue);
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
         boolean notMultiple = l != 0 || r != 0;
         if (notMultiple) {
             RError.warning(RError.Message.LENGTH_NOT_MULTI);
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA());
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA());
         ret.setDimensions(left.hasDimensions() ? left.getDimensions() : right.getDimensions(), this.getSourceSection());
         ret.copyNamesFrom(leftLength == resultLength ? left : right);
         return ret;
@@ -1825,15 +1888,20 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         assert areSameLength(left, right);
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             String leftValue = left.getDataAt(i);
             String rightValue = right.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue);
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.hasDimensions() ? left.getDimensions() : right.getDimensions());
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(),
+                        left.hasDimensions() ? left.getDimensions() : right.getDimensions());
         ret.copyNamesFrom(left.getNames() != null && left.getNames() != RNull.instance ? left : right);
         return ret;
     }
@@ -1844,21 +1912,25 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         int rightLength = right.getLength();
         int resultLength = Math.max(leftLength, rightLength);
         byte[] result = new byte[resultLength];
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
         int l = 0;
         int r = 0;
+        boolean naResult = false;
         for (int i = 0; i < resultLength; ++i, l = Utils.incMod(l, leftLength), r = Utils.incMod(r, rightLength)) {
             String leftValue = left.getDataAt(l);
             String rightValue = right.getDataAt(r);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue);
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
         boolean notMultiple = l != 0 || r != 0;
         if (notMultiple) {
             RError.warning(RError.Message.LENGTH_NOT_MULTI);
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA());
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA());
         ret.setDimensions(left.hasDimensions() ? left.getDimensions() : right.getDimensions(), this.getSourceSection());
         ret.copyNamesFrom(leftLength == resultLength ? left : right);
         return ret;
@@ -1870,15 +1942,20 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         assert areSameLength(left, right);
         int length = left.getLength();
         byte[] result = new byte[length];
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             RComplex leftValue = left.getDataAt(i);
             RComplex rightValue = right.getDataAt(i);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue);
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(), left.hasDimensions() ? left.getDimensions() : right.getDimensions());
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA(),
+                        left.hasDimensions() ? left.getDimensions() : right.getDimensions());
         ret.copyNamesFrom(left.getNames() != null && left.getNames() != RNull.instance ? left : right);
         return ret;
     }
@@ -1889,21 +1966,25 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         int rightLength = right.getLength();
         int resultLength = Math.max(leftLength, rightLength);
         byte[] result = new byte[resultLength];
-        leftNACheck.enable(!left.isComplete());
-        rightNACheck.enable(!right.isComplete());
+        leftNACheck.enable(left);
+        rightNACheck.enable(right);
         int l = 0;
         int r = 0;
+        boolean naResult = false;
         for (int i = 0; i < resultLength; ++i, l = Utils.incMod(l, leftLength), r = Utils.incMod(r, rightLength)) {
             RComplex leftValue = left.getDataAt(l);
             RComplex rightValue = right.getDataAt(r);
             byte resultValue = leftNACheck.check(leftValue) || rightNACheck.check(rightValue) ? RRuntime.LOGICAL_NA : logic.op(leftValue, rightValue);
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
         boolean notMultiple = l != 0 || r != 0;
         if (notMultiple) {
             RError.warning(RError.Message.LENGTH_NOT_MULTI);
         }
-        RLogicalVector ret = RDataFactory.createLogicalVector(result, leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA());
+        RLogicalVector ret = RDataFactory.createLogicalVector(result, !naResult && leftNACheck.neverSeenNA() && rightNACheck.neverSeenNA());
         ret.setDimensions(left.hasDimensions() ? left.getDimensions() : right.getDimensions(), this.getSourceSection());
         ret.copyNamesFrom(leftLength == resultLength ? left : right);
         return ret;
@@ -1915,10 +1996,14 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         assert areSameLength(left, right);
         int length = left.getLength();
         byte[] result = new byte[length];
+        boolean naResult = false;
         for (int i = 0; i < length; ++i) {
             RRaw leftValue = left.getDataAt(i);
             RRaw rightValue = right.getDataAt(i);
             byte resultValue = logic.op(leftValue, rightValue).getValue();
+            if (resultNAProfile.isNA(resultValue)) {
+                naResult = true;
+            }
             result[i] = resultValue;
         }
         RRawVector ret = RDataFactory.createRawVector(result, left.hasDimensions() ? left.getDimensions() : right.getDimensions());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryNode.java
index 9f6f63829b619000eb2bbfb0628951d4529ec63d..cb95bbc879f74aa6fc59ae700e01c2d25f24502b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryNode.java
@@ -47,7 +47,7 @@ public abstract class CombineBinaryNode extends BinaryNode {
             namesData[i++] = RRuntime.NAMES_ATTR_EMPTY_VALUE;
             to++;
         }
-        naCheck.enable(!orgNames.isComplete());
+        naCheck.enable(orgNames);
         for (int j = 0; i < to; i++, j++) {
             namesData[i] = orgNames.getDataAt(j);
             naCheck.check(namesData[i]);
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 4717be1f29d280a3beb9f5f8312abfa54ac99bbc..0f66f70bf44cba1c939992caa69760b3531ce819 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
@@ -79,7 +79,7 @@ public abstract class CastStringNode extends CastNode {
         for (int i = 0; i < operand.getLength(); i++) {
             sdata[i] = elementFunction.apply(i);
         }
-        RStringVector ret = RDataFactory.createStringVector(sdata, RDataFactory.COMPLETE_VECTOR, isPreserveDimensions() ? operand.getDimensions() : null, isPreserveNames() ? operand.getNames() : null);
+        RStringVector ret = RDataFactory.createStringVector(sdata, operand.isComplete(), isPreserveDimensions() ? operand.getDimensions() : null, isPreserveNames() ? operand.getNames() : null);
         if (isAttrPreservation()) {
             ret.copyRegAttributesFrom(operand);
         }
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 bc46cceb0891e71932cfdcde91384bc64e36663b..3caa924bf46ae9949f857ce71ff1701b605083ec 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
@@ -188,8 +188,9 @@ public abstract class UnaryArithmeticReduceNode extends UnaryNode {
         int result = semantics.getIntStart();
         na.enable(operand);
         int opCount = 0;
+        int[] data = operand.getDataWithoutCopying();
         for (int i = 0; i < operand.getLength(); i++) {
-            int d = operand.getDataAt(i);
+            int d = data[i];
             if (na.check(d)) {
                 if (profiledNaRm) {
                     continue;
@@ -213,8 +214,9 @@ public abstract class UnaryArithmeticReduceNode extends UnaryNode {
         double result = semantics.getDoubleStart();
         na.enable(operand);
         int opCount = 0;
+        double[] data = operand.getDataWithoutCopying();
         for (int i = 0; i < operand.getLength(); i++) {
-            double d = operand.getDataAt(i);
+            double d = data[i];
             if (na.check(d)) {
                 if (profiledNaRm) {
                     continue;
@@ -238,8 +240,9 @@ public abstract class UnaryArithmeticReduceNode extends UnaryNode {
         int result = semantics.getIntStart();
         na.enable(operand);
         int opCount = 0;
+        byte[] data = operand.getDataWithoutCopying();
         for (int i = 0; i < operand.getLength(); i++) {
-            byte d = operand.getDataAt(i);
+            byte d = data[i];
             if (na.check(d)) {
                 if (profiledNaRm) {
                     continue;
diff --git a/com.oracle.truffle.r.options/src/com/oracle/truffle/r/options/FastROptions.java b/com.oracle.truffle.r.options/src/com/oracle/truffle/r/options/FastROptions.java
index d0f669c5918b76e8ae103f9795796f50c1e238f2..aac24c0f60c7e11bf34cfb60aa6971395fd63487 100644
--- a/com.oracle.truffle.r.options/src/com/oracle/truffle/r/options/FastROptions.java
+++ b/com.oracle.truffle.r.options/src/com/oracle/truffle/r/options/FastROptions.java
@@ -45,6 +45,8 @@ public class FastROptions {
     public static final OptionValue<Boolean> DisableGroupGenerics = new OptionValue<>(false);
     @Option(help = "Prints Java and R stack traces for all R errors")
     public static final OptionValue<Boolean> PrintErrorStacktraces = new OptionValue<>(false);
+    @Option(help = "Check completeness of results vectors after evaluating unit tests and R shell commands")
+    public static final OptionValue<Boolean> CheckResultCompleteness = new OptionValue<>(false);
     @Option(help = "Turn on debugging output")
     public static final OptionValue<Boolean> Debug = new OptionValue<>(false);
     //@formatter:on
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 142faa3d20115284bda225ce5cc0b50a8203ec59..b783eead375f9cc9f38b016495942860c45492c1 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
@@ -58,7 +58,15 @@ public final class RComplexVector extends RVector implements RAbstractComplexVec
     @Override
     @TruffleBoundary
     public String toString() {
-        return Arrays.toString(data);
+        StringBuilder str = new StringBuilder();
+        str.append('[');
+        for (int i = 0; i < getLength(); i++) {
+            if (i > 0) {
+                str.append(", ");
+            }
+            str.append(RRuntime.complexToString(getDataAt(i)));
+        }
+        return str.append(']').toString();
     }
 
     @Override
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 7fedee60cd8f6318d01cbfe4de1badbab478fdd8..e85b400ca1541f7116df80ee432799edbf5bb68b 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
@@ -76,7 +76,7 @@ public final class RDoubleVector extends RVector implements RAbstractDoubleVecto
     @Override
     @TruffleBoundary
     public String toString() {
-        return Arrays.toString(data);
+        return Arrays.toString(Arrays.stream(data).mapToObj(v -> RRuntime.doubleToString(v)).toArray(String[]::new));
     }
 
     public RIntVector trimToIntVector() {
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 ec171ebbb0b01f2170e7815391ba56a3103267fa..057da30c232174dc72385ded460c8ab48c30e2a7 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
@@ -80,7 +80,7 @@ public final class RIntVector extends RVector implements RAbstractIntVector {
     @Override
     @TruffleBoundary
     public String toString() {
-        return Arrays.toString(data);
+        return Arrays.toString(Arrays.stream(data).mapToObj(v -> RRuntime.intToString(v, false)).toArray(String[]::new));
     }
 
     @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 951e1100c4ca0604a74a32fb865c6eac0477b166..22d760d56d3a49a013595a91ddfad5fefa517d05 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
@@ -228,4 +228,8 @@ public final class RList extends RVector implements RAbstractVector {
     protected RStringVector getImplicitClassHr() {
         return getClassHierarchyHelper(new String[]{RType.List.getName()}, implicitClassHrDyn);
     }
+
+    public boolean checkCompleteness() {
+        return true;
+    }
 }
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 79a4b7e6288aa6b28271eaa1b5a94047837f03b6..1c082f82108c668cf516334aec7125a03a6ab33b 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.model;
 
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 
 public interface RAbstractComplexVector extends RAbstractVector {
@@ -29,4 +30,13 @@ public interface RAbstractComplexVector extends RAbstractVector {
     RComplex getDataAt(int index);
 
     RComplexVector materialize();
+
+    default boolean checkCompleteness() {
+        for (int i = 0; i < getLength(); i++) {
+            if (RRuntime.isNA(getDataAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
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 127b31863315e0c3f7bb20f9ed2bed1ddb3a6a46..e6c33808488210230aa557ed2a11b9ded8b71f39 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.model;
 
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 
 public interface RAbstractDoubleVector extends RAbstractVector {
@@ -29,4 +30,13 @@ public interface RAbstractDoubleVector extends RAbstractVector {
     double getDataAt(int index);
 
     RDoubleVector materialize();
+
+    default boolean checkCompleteness() {
+        for (int i = 0; i < getLength(); i++) {
+            if (RRuntime.isNA(getDataAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
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 8343c3eedf76427b6e70260fec6d7fd50fdf08c8..8816c9b84a6a207db09df43cc5ebc5df7755152d 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.model;
 
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 
 public interface RAbstractIntVector extends RAbstractVector {
@@ -29,4 +30,13 @@ public interface RAbstractIntVector extends RAbstractVector {
     int getDataAt(int index);
 
     RIntVector materialize();
+
+    default boolean checkCompleteness() {
+        for (int i = 0; i < getLength(); i++) {
+            if (RRuntime.isNA(getDataAt(i))) {
+                return false;
+            }
+        }
+        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 488a05343342413772b612ac3b76f1926dff0e90..4006121efda1dd2531926610f83e871cb3f9b3f7 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.model;
 
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 
 public interface RAbstractLogicalVector extends RAbstractVector {
@@ -29,4 +30,13 @@ public interface RAbstractLogicalVector extends RAbstractVector {
     byte getDataAt(int index);
 
     RLogicalVector materialize();
+
+    default boolean checkCompleteness() {
+        for (int i = 0; i < getLength(); i++) {
+            if (RRuntime.isNA(getDataAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
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 117fe94b4191c86858be2b963c44017041626707..a7a57b11f18438fa4dd7b868df747c49c6d599a8 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
@@ -29,4 +29,8 @@ public interface RAbstractRawVector extends RAbstractVector {
     RRaw getDataAt(int index);
 
     RRawVector materialize();
+
+    default boolean checkCompleteness() {
+        return true;
+    }
 }
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 15c8c146f5174b1aa59c2ac2964c88247470571f..afa2918e9fab45b679d7ffb79cb66f13c76aa749 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.model;
 
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 
 public interface RAbstractStringVector extends RAbstractVector {
@@ -29,4 +30,13 @@ public interface RAbstractStringVector extends RAbstractVector {
     String getDataAt(int index);
 
     RStringVector materialize();
+
+    default boolean checkCompleteness() {
+        for (int i = 0; i < getLength(); i++) {
+            if (RRuntime.isNA(getDataAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
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 c1323361647f70cbc6746bd335e5b9434b9a8cd8..be75a9dfbea297a5d3b7bdb05981f63e80e1f61c 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
@@ -65,4 +65,6 @@ public interface RAbstractVector extends RAbstractContainer {
     boolean isMatrix();
 
     boolean isArray();
+
+    boolean checkCompleteness();
 }
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 bc37448c2807ca0676a435d9682e58efc4baffbd..e1d0e1e5631a15d31028ea6d862303d411842ee1 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
@@ -56,74 +56,15 @@ public abstract class BinaryArithmetic extends Operation {
     public static class PowBuiltin {
     }
 
-    public static final BinaryArithmeticFactory ADD = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new Add();
-        }
-    };
-    public static final BinaryArithmeticFactory SUBTRACT = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new Subtract();
-        }
-    };
-    public static final BinaryArithmeticFactory MULTIPLY = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new Multiply();
-        }
-    };
-    public static final BinaryArithmeticFactory INTEGER_DIV = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new IntegerDiv();
-        }
-    };
-
-    public static final BinaryArithmeticFactory DIV = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new Div();
-        }
-    };
-
-    public static final BinaryArithmeticFactory MOD = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new Mod();
-        }
-    };
-
-    public static final BinaryArithmeticFactory POW = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new Pow();
-        }
-    };
-
-    public static final BinaryArithmeticFactory MAX = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new Max();
-        }
-    };
-
-    public static final BinaryArithmeticFactory MIN = new BinaryArithmeticFactory() {
-
-        @Override
-        public BinaryArithmetic create() {
-            return new Min();
-        }
-    };
+    public static final BinaryArithmeticFactory ADD = Add::new;
+    public static final BinaryArithmeticFactory SUBTRACT = Subtract::new;
+    public static final BinaryArithmeticFactory MULTIPLY = Multiply::new;
+    public static final BinaryArithmeticFactory INTEGER_DIV = IntegerDiv::new;
+    public static final BinaryArithmeticFactory DIV = Div::new;
+    public static final BinaryArithmeticFactory MOD = Mod::new;
+    public static final BinaryArithmeticFactory POW = Pow::new;
+    public static final BinaryArithmeticFactory MAX = Max::new;
+    public static final BinaryArithmeticFactory MIN = Min::new;
 
     private final boolean supportsIntResult;
 
@@ -317,12 +258,10 @@ public abstract class BinaryArithmetic extends Operation {
             double[] res = new double[2];
             double[] interm = new double[4];
             complexMult(leftReal, leftImag, rightReal, rightImag, res, interm);
-            if (Double.isNaN(res[0]) && Double.isNaN(res[1])) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                MultiplyNaN multNaN = new MultiplyNaN();
-                replace(multNaN);
-                return multNaN.handleNaN(leftReal, leftImag, rightReal, rightImag, res, interm);
-            }
+            /*
+             * LStadler: removed the special code for handling NaNs in the result, since it works
+             * fine (and the tests are broken either way). to revive it, get it from the history.
+             */
             return RDataFactory.createComplex(res[0], res[1]);
         }
 
@@ -356,59 +295,6 @@ public abstract class BinaryArithmetic extends Operation {
 
     }
 
-    private static final class MultiplyNaN extends Multiply {
-
-        private final ConditionProfile inf1 = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile inf2 = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile inf3 = ConditionProfile.createBinaryProfile();
-
-        @Override
-        public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) {
-            double[] res = new double[2];
-            double[] interm = new double[4];
-            complexMult(leftReal, leftImag, rightReal, rightImag, res, interm);
-            if (Double.isNaN(res[0]) && Double.isNaN(res[1])) {
-                return handleNaN(leftReal, leftImag, rightReal, rightImag, res, interm);
-            }
-            return RDataFactory.createComplex(res[0], res[1]);
-        }
-
-        protected RComplex handleNaN(double leftReal, double leftImag, double rightReal, double rightImag, double[] res, double[] interm) {
-            boolean recalc = false;
-            double ra = leftReal;
-            double rb = leftImag;
-            double rc = rightReal;
-            double rd = rightImag;
-            if (inf1.profile(Double.isInfinite(ra) || Double.isInfinite(rb))) {
-                ra = convertInf(ra);
-                rb = convertInf(rb);
-                rc = convertNaN(rc);
-                rd = convertNaN(rd);
-                recalc = true;
-            }
-            if (inf2.profile(Double.isInfinite(rc) || Double.isInfinite(rd))) {
-                rc = convertInf(rc);
-                rd = convertInf(rd);
-                ra = convertNaN(ra);
-                rb = convertNaN(rb);
-                recalc = true;
-            }
-            if (inf3.profile(!recalc && (Double.isInfinite(interm[0]) || Double.isInfinite(interm[1]) || Double.isInfinite(interm[2]) || Double.isInfinite(interm[3])))) {
-                ra = convertNaN(ra);
-                rb = convertNaN(rb);
-                rc = convertNaN(rc);
-                rd = convertNaN(rd);
-                recalc = true;
-            }
-            if (recalc) {
-                res[0] = Double.POSITIVE_INFINITY * (ra * rc - rb * rd);
-                res[1] = Double.POSITIVE_INFINITY * (ra * rd + rb * rc);
-            }
-            return RDataFactory.createComplex(res[0], res[1]);
-        }
-
-    }
-
     private static class Div extends BinaryArithmetic {
 
         public Div() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmeticFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmeticFactory.java
index 9caa9b4a99b2bdcb8e5b3dc2ed20b64b77a1bbe3..9f50120d8538d7397ddd1df55fde8a5c0fa17c3c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmeticFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmeticFactory.java
@@ -22,8 +22,8 @@
  */
 package com.oracle.truffle.r.runtime.ops;
 
-public abstract class BinaryArithmeticFactory extends OperationFactory {
+@FunctionalInterface
+public interface BinaryArithmeticFactory extends OperationFactory {
 
-    @Override
-    public abstract BinaryArithmetic create();
+    BinaryArithmetic create();
 }
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 0a614dc224f5f5cafc84402517093fa10a96b075..51cdb19edf48abf7f758ab631bea9fc27e096362 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
@@ -52,49 +52,12 @@ public abstract class BinaryCompare extends BooleanOperation {
     public static class LessBuiltin {
     }
 
-    public static final BooleanOperationFactory NOT_EQUAL = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new NotEqual();
-        }
-    };
-
-    public static final BooleanOperationFactory EQUAL = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new Equal();
-        }
-    };
-    public static final BooleanOperationFactory GREATER_EQUAL = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new GreaterEqual();
-        }
-    };
-    public static final BooleanOperationFactory GREATER_THAN = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new GreaterThan();
-        }
-    };
-    public static final BooleanOperationFactory LESS_EQUAL = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new LessEqual();
-        }
-    };
-    public static final BooleanOperationFactory LESS_THAN = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new LessThan();
-        }
-    };
+    public static final BooleanOperationFactory NOT_EQUAL = NotEqual::new;
+    public static final BooleanOperationFactory EQUAL = Equal::new;
+    public static final BooleanOperationFactory GREATER_EQUAL = GreaterEqual::new;
+    public static final BooleanOperationFactory GREATER_THAN = GreaterThan::new;
+    public static final BooleanOperationFactory LESS_EQUAL = LessEqual::new;
+    public static final BooleanOperationFactory LESS_THAN = LessThan::new;
 
     public BinaryCompare(boolean commutative) {
         super(commutative, false);
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 42927099a3de6bf569d405f045840cb42418b2dc..94c72adc0dcbc11335e660fd73e30ada409e4b1a 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
@@ -45,37 +45,10 @@ public abstract class BinaryLogic extends BooleanOperation {
     public static class OrBuiltin {
     }
 
-    public static final BooleanOperationFactory NON_VECTOR_AND = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new NonVectorAnd();
-        }
-    };
-
-    public static final BooleanOperationFactory NON_VECTOR_OR = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new NonVectorOr();
-        }
-    };
-
-    public static final BooleanOperationFactory AND = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new And();
-        }
-    };
-
-    public static final BooleanOperationFactory OR = new BooleanOperationFactory() {
-
-        @Override
-        public BooleanOperation create() {
-            return new Or();
-        }
-    };
+    public static final BooleanOperationFactory NON_VECTOR_AND = NonVectorAnd::new;
+    public static final BooleanOperationFactory NON_VECTOR_OR = NonVectorOr::new;
+    public static final BooleanOperationFactory AND = And::new;
+    public static final BooleanOperationFactory OR = Or::new;
 
     public BinaryLogic() {
         super(true, true);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BooleanOperationFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BooleanOperationFactory.java
index 01745f511a9dd2ac7a23f3746dc1adb2af969618..fd6384e5912b01dd4b76e6abdb683116a81e335c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BooleanOperationFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BooleanOperationFactory.java
@@ -22,8 +22,8 @@
  */
 package com.oracle.truffle.r.runtime.ops;
 
-public abstract class BooleanOperationFactory extends OperationFactory {
+@FunctionalInterface
+public interface BooleanOperationFactory extends OperationFactory {
 
-    @Override
-    public abstract BooleanOperation create();
+    BooleanOperation create();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/OperationFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/OperationFactory.java
index f16147f68a116e347044b91123675486063fd6ec..1b92f75b313a6b2eb46db509df55f9a3fb452dec 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/OperationFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/OperationFactory.java
@@ -22,8 +22,9 @@
  */
 package com.oracle.truffle.r.runtime.ops;
 
-public abstract class OperationFactory {
+@FunctionalInterface
+public interface OperationFactory {
 
-    public abstract Operation create();
+    Operation create();
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
index b270f54a42a09c62d795a98dd5f84324af1c8b49..e141953c1740070644f3da42550cfe81c90b2b61 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
@@ -20,37 +20,10 @@ import com.oracle.truffle.r.runtime.data.*;
 
 public abstract class UnaryArithmetic extends Operation {
 
-    public static final UnaryArithmeticFactory NEGATE = new UnaryArithmeticFactory() {
-
-        @Override
-        public UnaryArithmetic create() {
-            return new Negate();
-        }
-    };
-
-    public static final UnaryArithmeticFactory ROUND = new UnaryArithmeticFactory() {
-
-        @Override
-        public UnaryArithmetic create() {
-            return new Round();
-        }
-    };
-
-    public static final UnaryArithmeticFactory FLOOR = new UnaryArithmeticFactory() {
-
-        @Override
-        public UnaryArithmetic create() {
-            return new Floor();
-        }
-    };
-
-    public static final UnaryArithmeticFactory CEILING = new UnaryArithmeticFactory() {
-
-        @Override
-        public UnaryArithmetic create() {
-            return new Ceiling();
-        }
-    };
+    public static final UnaryArithmeticFactory NEGATE = Negate::new;
+    public static final UnaryArithmeticFactory ROUND = Round::new;
+    public static final UnaryArithmeticFactory FLOOR = Floor::new;
+    public static final UnaryArithmeticFactory CEILING = Ceiling::new;
 
     public UnaryArithmetic() {
         super(false, false);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmeticFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmeticFactory.java
index 19ef9e17c4952e0bdf3b3b932257589b5efd6670..07a19b5d3891d4e2fd8e6a194766c5efd3cc6dea 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmeticFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmeticFactory.java
@@ -22,8 +22,8 @@
  */
 package com.oracle.truffle.r.runtime.ops;
 
-public abstract class UnaryArithmeticFactory extends OperationFactory {
+@FunctionalInterface
+public interface UnaryArithmeticFactory extends OperationFactory {
 
-    @Override
-    public abstract UnaryArithmetic create();
+    UnaryArithmetic create();
 }