From 56f5b39788d78542bfab4b1718956f2472514012 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 19 Jan 2017 14:49:46 +0100
Subject: [PATCH] simplify RAbstractVector (remove setNA) and
 PositionCheckSubsetNode, incMod with profile

---
 .../base/printer/ValuePrinterNode.java        |  5 -
 .../vector/PositionCheckSubsetNode.java       | 45 +++++----
 .../access/vector/WriteIndexedVectorNode.java | 98 +++++++++++--------
 .../r/nodes/binary/BinaryArithmeticNode.java  |  9 +-
 .../r/nodes/primitive/BinaryMapNode.java      |  8 +-
 .../com/oracle/truffle/r/runtime/Utils.java   |  9 ++
 .../truffle/r/runtime/data/RExpression.java   |  5 -
 .../data/model/RAbstractComplexVector.java    |  7 +-
 .../data/model/RAbstractDoubleVector.java     |  7 +-
 .../data/model/RAbstractIntVector.java        |  7 +-
 .../data/model/RAbstractListBaseVector.java   |  9 +-
 .../data/model/RAbstractLogicalVector.java    |  7 +-
 .../data/model/RAbstractRawVector.java        |  6 +-
 .../data/model/RAbstractStringVector.java     |  7 +-
 .../r/runtime/data/model/RAbstractVector.java |  4 +-
 15 files changed, 107 insertions(+), 126 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 25ed8d70c1..16b9bb88af 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
@@ -485,11 +485,6 @@ public final class ValuePrinterNode extends RBaseNode {
             throw RInternalError.shouldNotReachHere();
         }
 
-        @Override
-        public void setNA(Object store, int index) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
         @Override
         public boolean isComplete() {
             return false;
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 5ae6b0a5ac..208b079a8a 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
@@ -65,7 +65,8 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
 
     @Specialization(guards = {"isMultiplesOf(dimensionLength, positionLength)", "positionLength <= dimensionLength"})
     protected RAbstractVector doLogicalMultiplesInBounds(PositionProfile statistics, int dimensionLength, RAbstractLogicalVector position, int positionLength,
-                    @Cached("createCountingProfile()") LoopConditionProfile lengthProfile) {
+                    @Cached("createCountingProfile()") LoopConditionProfile lengthProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile equalsProfile) {
         assert positionLength > 0;
         positionNACheck.enable(position);
         int elementCount = 0;
@@ -83,7 +84,7 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
         }
         statistics.containsNA = hasSeenNA;
         statistics.maxOutOfBoundsIndex = positionLength;
-        statistics.selectedPositionsCount = elementCount * (dimensionLength / positionLength);
+        statistics.selectedPositionsCount = elementCount * (equalsProfile.profile(dimensionLength == positionLength) ? 1 : dimensionLength / positionLength);
         return position;
     }
 
@@ -94,7 +95,8 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
     @Specialization(contains = "doLogicalMultiplesInBounds")
     protected RAbstractVector doLogicalGenericInBounds(PositionProfile statistics,  //
                     int dimensionLength, RAbstractLogicalVector position, int positionLength, @Cached("create()") BranchProfile outOfBoundsProfile,
-                    @Cached("createCountingProfile()") LoopConditionProfile lengthProfile) {
+                    @Cached("createCountingProfile()") LoopConditionProfile lengthProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile incModProfile) {
         positionNACheck.enable(position);
         int positionIndex = 0;
         int elementCount = 0;
@@ -120,7 +122,7 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
                 if (positionValue == RRuntime.LOGICAL_TRUE) {
                     elementCount++;
                 }
-                positionIndex = Utils.incMod(positionIndex, positionLength);
+                positionIndex = Utils.incMod(positionIndex, positionLength, incModProfile);
             }
         }
         statistics.containsNA = hasSeenNA;
@@ -134,6 +136,7 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
                     @Cached("create()") BranchProfile seenZeroProfile,
                     @Cached("create()") BranchProfile seenPositiveProfile,
                     @Cached("create()") BranchProfile seenNegativeProfile,
+                    @Cached("create()") BranchProfile seenNegativeZeroProfile,
                     @Cached("create()") BranchProfile seenOutOfBounds,
                     @Cached("create()") NullProfile hasNamesProfile,
                     @Cached("createCountingProfile()") LoopConditionProfile lengthProfile,
@@ -158,34 +161,36 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
         lengthProfile.profileCounted(positionLength);
         for (int i = 0; lengthProfile.inject(i < positionLength); i++) {
             double positionValue = position.getDataAt(i);
-            if (positionValue >= 1) {
+            int intPositionValue = RRuntime.double2intNoCheck(positionValue);
+
+            if (intPositionValue > 0) {
                 seenPositiveProfile.enter();
                 hasSeenPositive = true;
-                int intPositionValue = RRuntime.double2intNoCheck(positionValue);
-                if (positionValue > dimensionLength) {
+                if (intPositionValue > dimensionLength) {
                     seenOutOfBounds.enter();
                     outOfBoundsCount++;
                     maxOutOfBoundsIndex = Math.max(maxOutOfBoundsIndex, intPositionValue);
                 }
-                intPosition.setDataAt(convertedStore, i, intPositionValue);
-            } else if (positionValue >= 0 && positionValue < 1) {
+            } else if (intPositionValue == 0) {
                 seenZeroProfile.enter();
-                zeroCount++;
-            } else if (positionNACheck.checkNAorNaN(positionValue)) {
-                hasSeenNA = true;
-                intPosition.setNA(convertedStore, i);
-            } else {
-                seenNegativeProfile.enter();
-                assert positionValue < 0;
-                hasSeenNegative = true;
-                int intPositionValue = RRuntime.double2intNoCheck(positionValue);
-                if (intPositionValue == 0) {
+                if (positionValue < 0) {
+                    seenNegativeZeroProfile.enter();
                     /*
                      * It seems that the range ]-2:0[ is all translated to -1. So much for
                      * continuous math properties.
                      */
+                    hasSeenNegative = true;
                     intPositionValue = -1;
+                } else if (positionNACheck.checkNAorNaN(positionValue)) {
+                    hasSeenNA = true;
+                    intPositionValue = RRuntime.INT_NA;
+                } else {
+                    zeroCount++;
                 }
+            } else {
+                seenNegativeProfile.enter();
+                assert positionValue < 0;
+                hasSeenNegative = true;
                 if (-positionValue > dimensionLength) {
                     seenOutOfBounds.enter();
                     outOfBoundsCount++;
@@ -195,8 +200,8 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
                      */
                     intPositionValue--;
                 }
-                intPosition.setDataAt(convertedStore, i, intPositionValue);
             }
+            intPosition.setDataAt(convertedStore, i, intPositionValue);
         }
         return doIntegerProfiled(profile, dimensionLength, intPosition, positionLength, hasSeenPositive, hasSeenNegative, hasSeenNA, outOfBoundsCount, zeroCount, maxOutOfBoundsIndex);
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java
index 5c7e80a72e..47861018bb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.access.vector;
 
-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.nodes.Node;
@@ -44,6 +42,7 @@ import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RScalarVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -84,6 +83,7 @@ abstract class WriteIndexedVectorNode extends Node {
     private final VectorLengthProfile dimensionValueProfile = VectorLengthProfile.create();
     private final ValueProfile positionClassProfile = ValueProfile.createClassProfile();
     private final NACheck positionNACheck = NACheck.create();
+    private final ConditionProfile resetIndexProfile = ConditionProfile.createBinaryProfile();
 
     @Child private WriteIndexedScalarNode<RAbstractVector, RTypedValue> scalarNode;
     @Child private WriteIndexedVectorNode innerVectorNode;
@@ -196,8 +196,6 @@ abstract class WriteIndexedVectorNode extends Node {
                     Object[] positions, RMissing position, int positionOffset, int positionLength,
                     RAbstractContainer right, Object rightStore, int rightBase, int rightLength, boolean parentNA,
                     @Cached("createCountingProfile()") LoopConditionProfile profile) {
-        initRightIndexCheck(rightBase, targetDimension, leftLength, rightLength);
-
         int rightIndex = rightBase;
         profile.profileCounted(targetDimension);
         for (int positionValue = 0; profile.inject(positionValue < targetDimension); positionValue += 1) {
@@ -214,7 +212,8 @@ abstract class WriteIndexedVectorNode extends Node {
                     Object[] positions, RAbstractLogicalVector position, int positionOffset, int positionLength,
                     RTypedValue right, Object rightStore, int rightBase, int rightLength, boolean parentNA,
                     @Cached("create()") BranchProfile wasTrue, @Cached("create()") AlwaysOnBranchProfile outOfBounds,
-                    @Cached("createCountingProfile()") LoopConditionProfile profile) {
+                    @Cached("createCountingProfile()") LoopConditionProfile profile,
+                    @Cached("createBinaryProfile()") ConditionProfile incModProfile) {
         positionNACheck.enable(!skipNA && !position.isComplete());
 
         int length = targetDimension;
@@ -226,8 +225,6 @@ abstract class WriteIndexedVectorNode extends Node {
         int rightIndex = rightBase;
         if (positionLength > 0) {
 
-            initRightIndexCheck(rightBase, length, leftLength, rightLength);
-
             int positionIndex = 0;
             profile.profileCounted(length);
             for (int i = 0; profile.inject(i < length); i++) {
@@ -243,14 +240,12 @@ abstract class WriteIndexedVectorNode extends Node {
                                     positions, positionOffset, i,
                                     right, rightStore, rightLength, rightIndex, isNA || parentNA);
                 }
-                positionIndex = Utils.incMod(positionIndex, positionLength);
+                positionIndex = Utils.incMod(positionIndex, positionLength, incModProfile);
             }
         }
         return rightIndex;
     }
 
-    @CompilationFinal private boolean needsRightIndexCheck = false;
-
     /**
      * For integer sequences we need to make sure that start and stride is profiled.
      *
@@ -274,8 +269,6 @@ abstract class WriteIndexedVectorNode extends Node {
             throw new SlowPathException("rewrite to doIntegerPosition");
         }
 
-        initRightIndexCheck(rightBase, positionLength, leftLength, rightLength);
-
         boolean ascending = conditionProfile.profile(start < end);
         profile.profileCounted(positionLength);
         for (int positionValue = start; profile.inject(ascending ? positionValue < end : positionValue > end); positionValue += stride) {
@@ -287,20 +280,6 @@ abstract class WriteIndexedVectorNode extends Node {
         return rightIndex;
     }
 
-    private void initRightIndexCheck(int rightBase, int positionLength, int leftLength, int rightLength) {
-        if (!needsRightIndexCheck) {
-            int actionRightMod = positionsApplyToRight ? leftLength : rightLength;
-            if (rightBase + positionLength > actionRightMod) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                WriteIndexedVectorNode writeVector = this;
-                while (writeVector != null) {
-                    writeVector.needsRightIndexCheck = true;
-                    writeVector = writeVector.innerVectorNode;
-                }
-            }
-        }
-    }
-
     /**
      * Integer vectors iterate over the number of positions because we assume that the number of
      * positions in an integer vector is significantly lower than the number of elements in the
@@ -314,8 +293,6 @@ abstract class WriteIndexedVectorNode extends Node {
         positionNACheck.enable(position);
         int rightIndex = rightBase;
 
-        initRightIndexCheck(rightBase, positionLength, leftLength, rightLength);
-
         lengthProfile.profileCounted(positionLength);
         for (int i = 0; lengthProfile.inject(i < positionLength); i++) {
             int positionValue = position.getDataAt(i);
@@ -337,7 +314,7 @@ abstract class WriteIndexedVectorNode extends Node {
     private int applyInner(//
                     RAbstractVector left, Object leftStore, int leftBase, int leftLength, Object targetDimensions,
                     Object[] positions, int positionOffset, int positionValue,
-                    RTypedValue right, Object rightStore, int rightLength, int rightIndex, boolean isNA) {
+                    RTypedValue right, Object rightStore, int rightLength, int actionIndex, boolean isNA) {
         int newTargetIndex = leftBase + positionValue * positionOffset;
         if (dimensionIndex == 0) {
             // for-loops leaf for innermost dimension
@@ -346,34 +323,30 @@ abstract class WriteIndexedVectorNode extends Node {
             int actionLeftIndex;
             int actionRightIndex;
             if (positionsApplyToRight) {
-                if (needsRightIndexCheck && rightIndex == leftLength) {
-                    rightIndex = 0;
-                }
-                actionLeftIndex = rightIndex;
+                actionLeftIndex = actionIndex;
                 actionRightIndex = newTargetIndex;
             } else {
-                if (needsRightIndexCheck && rightIndex == rightLength) {
-                    rightIndex = 0;
-                }
                 actionLeftIndex = newTargetIndex;
-                actionRightIndex = rightIndex;
+                actionRightIndex = actionIndex;
             }
 
             if (isNA) {
-                left.setNA(leftStore, actionLeftIndex);
-                getValueNACheck().seenNA();
+                scalarNode.applyNA(left, leftStore, actionLeftIndex);
             } else {
                 scalarNode.apply(left, leftStore, actionLeftIndex, right, rightStore, actionRightIndex);
             }
 
-            return rightIndex + 1;
+            if (resetIndexProfile.profile((actionIndex + 1) == (positionsApplyToRight ? leftLength : rightLength))) {
+                return 0;
+            }
+            return actionIndex + 1;
         } else {
             // generate another for-loop for other dimensions
             int nextTargetDimension = innerVectorNode.dimensionValueProfile.profile(((int[]) targetDimensions)[innerVectorNode.dimensionIndex]);
             return innerVectorNode.applyImpl(//
                             left, leftStore, newTargetIndex, leftLength, targetDimensions, nextTargetDimension,
                             positions, positionOffset,
-                            right, rightStore, rightIndex, rightLength, isNA);
+                            right, rightStore, actionIndex, rightLength, isNA);
         }
     }
 
@@ -407,6 +380,8 @@ abstract class WriteIndexedVectorNode extends Node {
 
         abstract void apply(A leftAccess, Object leftStore, int leftIndex, V rightAccess, Object rightStore, int rightIndex);
 
+        abstract void applyNA(A leftAccess, Object leftStore, int leftIndex);
+
     }
 
     private static final class WriteLogicalAction extends WriteIndexedScalarNode<RAbstractLogicalVector, RAbstractLogicalVector> {
@@ -417,6 +392,12 @@ abstract class WriteIndexedVectorNode extends Node {
             leftAccess.setDataAt(leftStore, leftIndex, value);
             valueNACheck.check(value);
         }
+
+        @Override
+        void applyNA(RAbstractLogicalVector leftAccess, Object leftStore, int leftIndex) {
+            leftAccess.setDataAt(leftStore, leftIndex, RRuntime.LOGICAL_NA);
+            valueNACheck.seenNA();
+        }
     }
 
     private static final class WriteIntegerAction extends WriteIndexedScalarNode<RAbstractIntVector, RAbstractIntVector> {
@@ -427,6 +408,12 @@ abstract class WriteIndexedVectorNode extends Node {
             leftAccess.setDataAt(leftStore, leftIndex, value);
             valueNACheck.check(value);
         }
+
+        @Override
+        void applyNA(RAbstractIntVector leftAccess, Object leftStore, int leftIndex) {
+            leftAccess.setDataAt(leftStore, leftIndex, RRuntime.INT_NA);
+            valueNACheck.seenNA();
+        }
     }
 
     private static final class WriteDoubleAction extends WriteIndexedScalarNode<RAbstractDoubleVector, RAbstractDoubleVector> {
@@ -437,6 +424,12 @@ abstract class WriteIndexedVectorNode extends Node {
             leftAccess.setDataAt(leftStore, leftIndex, value);
             valueNACheck.check(value);
         }
+
+        @Override
+        void applyNA(RAbstractDoubleVector leftAccess, Object leftStore, int leftIndex) {
+            leftAccess.setDataAt(leftStore, leftIndex, RRuntime.DOUBLE_NA);
+            valueNACheck.seenNA();
+        }
     }
 
     private static final class WriteComplexAction extends WriteIndexedScalarNode<RAbstractComplexVector, RAbstractComplexVector> {
@@ -447,6 +440,12 @@ abstract class WriteIndexedVectorNode extends Node {
             leftAccess.setDataAt(leftStore, leftIndex, value);
             valueNACheck.check(value);
         }
+
+        @Override
+        void applyNA(RAbstractComplexVector leftAccess, Object leftStore, int leftIndex) {
+            leftAccess.setDataAt(leftStore, leftIndex, RComplex.createNA());
+            valueNACheck.seenNA();
+        }
     }
 
     private static final class WriteCharacterAction extends WriteIndexedScalarNode<RAbstractStringVector, RAbstractStringVector> {
@@ -457,6 +456,12 @@ abstract class WriteIndexedVectorNode extends Node {
             leftAccess.setDataAt(leftStore, leftIndex, value);
             valueNACheck.check(value);
         }
+
+        @Override
+        void applyNA(RAbstractStringVector leftAccess, Object leftStore, int leftIndex) {
+            leftAccess.setDataAt(leftStore, leftIndex, RRuntime.STRING_NA);
+            valueNACheck.seenNA();
+        }
     }
 
     private static final class WriteRawAction extends WriteIndexedScalarNode<RAbstractRawVector, RAbstractRawVector> {
@@ -467,6 +472,11 @@ abstract class WriteIndexedVectorNode extends Node {
             leftAccess.setRawDataAt(leftStore, leftIndex, value);
             valueNACheck.check(value);
         }
+
+        @Override
+        void applyNA(RAbstractRawVector leftAccess, Object leftStore, int leftIndex) {
+            // nothing to do
+        }
     }
 
     private static final class WriteListAction extends WriteIndexedScalarNode<RAbstractListBaseVector, RTypedValue> {
@@ -512,5 +522,11 @@ abstract class WriteIndexedVectorNode extends Node {
             leftAccess.setDataAt(leftStore, leftIndex, rightValue);
             valueNACheck.checkListElement(rightValue);
         }
+
+        @Override
+        void applyNA(RAbstractListBaseVector leftAccess, Object leftStore, int leftIndex) {
+            leftAccess.setDataAt(leftStore, leftIndex, RNull.instance);
+            valueNACheck.seenNA();
+        }
     }
 }
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 d7496e23c6..09a759cdf2 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
@@ -105,8 +105,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
     }
 
     @Specialization
-    @SuppressWarnings("unused")
-    protected Object doUnary(Object left, RMissing right,
+    protected Object doUnary(Object left, @SuppressWarnings("unused") RMissing right,
                     @Cached("createUnaryArithmeticNode()") UnaryArithmeticNode unaryNode) {
         return unaryNode.execute(left);
     }
@@ -121,8 +120,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
     }
 
     @Specialization
-    @SuppressWarnings("unused")
-    protected static Object doBothNull(RNull left, RNull right) {
+    protected static Object doBothNull(@SuppressWarnings("unused") RNull left, @SuppressWarnings("unused") RNull right) {
         return RType.Double.getEmpty();
     }
 
@@ -142,9 +140,8 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
         return doLeftNull(right, left, classProfile);
     }
 
-    @SuppressWarnings("unused")
     @Fallback
-    protected Object doInvalidType(Object left, Object right) {
+    protected Object doInvalidType(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") Object right) {
         throw RError.error(this, Message.NON_NUMERIC_BINARY);
     }
 
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 7ed25db22d..d8c4d356fd 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
@@ -508,15 +508,17 @@ public final class BinaryMapNode extends RBaseNode {
 
         @Specialization(guards = {"!multiples(leftLength, rightLength)"})
         protected void doNoMultiples(BinaryMapFunctionNode node, Object store, RAbstractVector left, int leftLength, RAbstractVector right, int rightLength,
-                        @Cached("createCountingProfile()") LoopConditionProfile profile) {
+                        @Cached("createCountingProfile()") LoopConditionProfile profile,
+                        @Cached("createBinaryProfile()") ConditionProfile leftIncModProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile rightIncModProfile) {
             int j = 0;
             int k = 0;
             int max = Math.max(leftLength, rightLength);
             profile.profileCounted(max);
             for (int i = 0; profile.inject(i < max); ++i) {
                 indexedAction.perform(node, store, i, left, j, right, k);
-                j = Utils.incMod(j, leftLength);
-                k = Utils.incMod(k, rightLength);
+                j = Utils.incMod(j, leftLength, leftIncModProfile);
+                k = Utils.incMod(k, rightLength, rightIncModProfile);
             }
             RError.warning(this, RError.Message.LENGTH_NOT_MULTI);
         }
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 9bb2fb9d4f..0ac2c2b9e2 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
@@ -47,6 +47,7 @@ import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.FrameInstanceVisitor;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.nodes.GraphPrintVisitor;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
@@ -99,6 +100,14 @@ public final class Utils {
         return result;
     }
 
+    public static int incMod(int value, int mod, ConditionProfile profile) {
+        int result = (value + 1);
+        if (profile.profile(result == mod)) {
+            return 0;
+        }
+        return result;
+    }
+
     public static void dumpFunction(String groupName, RFunction function) {
         GraphPrintVisitor graphPrinter = new GraphPrintVisitor();
         RootCallTarget callTarget = function.getTarget();
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 2b81e39bc3..d4fed1887a 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
@@ -87,9 +87,4 @@ public class RExpression extends RListBase implements RAbstractVector {
     public RStringVector getImplicitClass() {
         return getClassHierarchyHelper(implicitClassHeader);
     }
-
-    @Override
-    public void setNA(Object store, int index) {
-        setDataAt(store, index, RNull.instance);
-    }
 }
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 3fcd5a0592..e3a04b4133 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
@@ -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
@@ -48,11 +48,6 @@ public interface RAbstractComplexVector extends RAbstractVector {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    default void setNA(Object store, int index) {
-        setDataAt(store, index, RComplex.createNA());
-    }
-
     @Override
     default boolean checkCompleteness() {
         for (int i = 0; i < getLength(); i++) {
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 8b09cd9bbe..b8f4e98d3b 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
@@ -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
@@ -45,11 +45,6 @@ public interface RAbstractDoubleVector extends RAbstractVector {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    default void setNA(Object store, int index) {
-        setDataAt(store, index, RRuntime.DOUBLE_NA);
-    }
-
     @Override
     RDoubleVector materialize();
 
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 58eee2a989..739bbaad05 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
@@ -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
@@ -45,11 +45,6 @@ public interface RAbstractIntVector extends RAbstractVector {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    default void setNA(Object store, int index) {
-        setDataAt(store, index, RRuntime.INT_NA);
-    }
-
     @Override
     RIntVector materialize();
 
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 0bf27c7035..edd08c2347 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
@@ -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,8 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.data.model;
 
-import com.oracle.truffle.r.runtime.data.RNull;
-
 public interface RAbstractListBaseVector extends RAbstractVector {
 
     @Override
@@ -50,9 +48,4 @@ public interface RAbstractListBaseVector extends RAbstractVector {
     default void setDataAt(Object store, int index, Object value) {
         throw new UnsupportedOperationException();
     }
-
-    @Override
-    default void setNA(Object store, int index) {
-        setDataAt(store, index, RNull.instance);
-    }
 }
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 4d610786da..2203663c5e 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
@@ -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
@@ -45,11 +45,6 @@ public interface RAbstractLogicalVector extends RAbstractVector {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    default void setNA(Object store, int index) {
-        setDataAt(store, index, RRuntime.LOGICAL_NA);
-    }
-
     @Override
     RLogicalVector materialize();
 
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 162d25bf5c..c1a8873d8d 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
@@ -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
@@ -42,10 +42,6 @@ public interface RAbstractRawVector extends RAbstractVector {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    default void setNA(Object store, int index) {
-    }
-
     RRaw getDataAt(int index);
 
     byte getRawDataAt(int index);
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 e15669bbb0..c21728a8c0 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
@@ -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
@@ -43,11 +43,6 @@ public interface RAbstractStringVector extends RAbstractVector {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    default void setNA(Object store, int index) {
-        setDataAt(store, index, RRuntime.STRING_NA);
-    }
-
     String getDataAt(int index);
 
     @Override
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 a6e9a39c04..bf9862638a 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
@@ -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
@@ -78,6 +78,4 @@ public interface RAbstractVector extends RAbstractContainer {
     }
 
     void setComplete(boolean complete);
-
-    void setNA(Object store, int index);
 }
-- 
GitLab