diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index cdb9f13b1c530c131cd8606ea5a29f683be5b4d2..8c7e60ef51c8b7702fac9021c1b41902a2c9d1fa 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -517,38 +517,43 @@ public final class FrameSlotChangeMonitor {
          */
 
         private void setValue(boolean value, FrameSlot slot) {
-            if (stableValue != null && (!(stableValue.getValue() instanceof Boolean) || ((boolean) stableValue.getValue()) != value)) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && (!(sv.getValue() instanceof Boolean) || ((boolean) sv.getValue()) != value)) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
         private void setValue(byte value, FrameSlot slot) {
-            if (stableValue != null && (!(stableValue.getValue() instanceof Byte) || ((byte) stableValue.getValue()) != value)) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && (!(sv.getValue() instanceof Byte) || ((byte) sv.getValue()) != value)) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
         private void setValue(int value, FrameSlot slot) {
-            if (stableValue != null && (!(stableValue.getValue() instanceof Integer) || ((int) stableValue.getValue()) != value)) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && (!(sv.getValue() instanceof Integer) || ((int) sv.getValue()) != value)) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
         private void setValue(double value, FrameSlot slot) {
-            if (stableValue != null && (!(stableValue.getValue() instanceof Double) || ((double) stableValue.getValue()) != value)) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && (!(sv.getValue() instanceof Double) || ((double) sv.getValue()) != value)) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
         private void setValue(Object value, FrameSlot slot) {
-            if (stableValue != null && stableValue.getValue() != value) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && sv.getValue() != value) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
-        private void invalidateStableValue(Object value, FrameSlot slot) {
+        private void invalidateStableValue(StableValue<Object> sv, Object value, FrameSlot slot) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            stableValue.getAssumption().invalidate();
+            sv.getAssumption().invalidate();
             if (invalidationCount > 0) {
                 invalidationCount--;
                 out("setting singleton value %s = %s", slot.getIdentifier(), value == null ? "null" : value.getClass());
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 1848dcc3027b5f61485c511c5f20890ba49d3ac1..e3359b65efa0f40bcb1ab07bf55ccae4c7918308 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
@@ -136,13 +136,14 @@ public abstract class BinaryArithmetic extends Operation {
 
         @Override
         public int op(int left, int right) {
-            try {
-                return ExactMath.addExact(left, right);
-            } catch (ArithmeticException e) {
+            int r = left + right;
+            // TODO: not using ExactMath because of perf problems
+            if (((left ^ r) & (right ^ r)) < 0) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 replace(new AddOverflow());
                 return INT_NA;
             }
+            return r;
         }
 
         @Override
@@ -193,13 +194,14 @@ public abstract class BinaryArithmetic extends Operation {
 
         @Override
         public int op(int left, int right) {
-            try {
-                return ExactMath.subtractExact(left, right);
-            } catch (ArithmeticException e) {
+            int r = left - right;
+            // TODO: not using ExactMath because of perf problems
+            if (((left ^ right) & (left ^ r)) < 0) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 replace(new SubtractOverflow());
                 return INT_NA;
             }
+            return r;
         }
 
         @Override
@@ -249,13 +251,14 @@ public abstract class BinaryArithmetic extends Operation {
 
         @Override
         public int op(int left, int right) {
-            try {
-                return ExactMath.multiplyExact(left, right);
-            } catch (ArithmeticException e) {
+            long r = (long) left * (long) right;
+            // TODO: not using ExactMath because of perf problems
+            if ((int) r != r) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 replace(new MultiplyOverflow());
                 return INT_NA;
             }
+            return (int) r;
         }
 
         @Override