diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
index 0938a7bde696bdfad94ecb9a0f34db6cd6b2bc73..a4f4376e81f3e66bcf3cb7b7ff17eae0670faeb9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
@@ -55,7 +55,7 @@ public abstract class APerm extends RBuiltinNode.Arg3 {
     static {
         Casts casts = new Casts(APerm.class);
         casts.arg("a").mustNotBeNull(RError.Message.FIRST_ARG_MUST_BE_ARRAY);
-        casts.arg("perm").allowNull().mustBe(numericValue().or(stringValue()).or(complexValue())).mapIf(numericValue().or(complexValue()), asIntegerVector());
+        casts.arg("perm").allowNull().mustBe(numericValue().or(stringValue()).or(complexValue())).mapIf(numericValue().or(complexValue()), asIntegerVector(true));
         casts.arg("resize").mustBe(numericValue().or(logicalValue()), Message.INVALID_LOGICAL, "resize").asLogicalVector().findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 70f34a3d31d1afd35087958cefe70a8de97c20a1..85c0769241a35b602183128d8678d083897131b7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -332,8 +332,16 @@ public final class CastBuilder {
             return new CoercionStep<>(RType.Integer, true);
         }
 
+        public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean reuseNonShared) {
+            return new CoercionStep<>(RType.Integer, true, false, false, false, true, reuseNonShared);
+        }
+
         public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-            return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true);
+            return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true, false);
+        }
+
+        public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean reuseNonShared) {
+            return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true, reuseNonShared);
         }
 
         public static <T> PipelineStep<T, Double> asDouble() {
@@ -377,7 +385,7 @@ public final class CastBuilder {
         }
 
         public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-            return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false);
+            return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false, false);
         }
 
         public static PipelineStep<Byte, Boolean> asBoolean() {
@@ -389,7 +397,7 @@ public final class CastBuilder {
         }
 
         public static <T> PipelineStep<T, RAbstractVector> asVector(boolean preserveNonVector) {
-            return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector);
+            return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector, false);
         }
 
         /**
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
index 7f4776692ec9714a69e551a85df015bd8896763d..c172a54400f2be7a297069425eb15d16a365cab0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
@@ -176,21 +176,27 @@ public abstract class PipelineStep<T, R> {
          */
         public final boolean vectorCoercion;
 
+        /**
+         * Whether the cast should reuse a non-shared vector.
+         */
+        public final boolean reuseNonShared;
+
         public CoercionStep(RType type, boolean vectorCoercion) {
-            this(type, vectorCoercion, false, false, false, true);
+            this(type, vectorCoercion, false, false, false, true, false);
         }
 
         public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-            this(type, vectorCoercion, preserveNames, preserveDimensions, preserveAttributes, true);
+            this(type, vectorCoercion, preserveNames, preserveDimensions, preserveAttributes, true, false);
         }
 
-        public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) {
+        public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector, boolean reuseNonShared) {
             this.type = type;
             this.vectorCoercion = vectorCoercion;
             this.preserveNames = preserveNames;
             this.preserveAttributes = preserveAttributes;
             this.preserveDimensions = preserveDimensions;
             this.preserveNonVector = preserveNonVector;
+            this.reuseNonShared = reuseNonShared;
         }
 
         public RType getType() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 12aaa0ec1f3df2f353fbc0bc633110f87b42698f..f9f7dde80c9c629b08eb5f684d7a35608535093a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -226,11 +226,11 @@ public final class PipelineToCastNode {
             RType type = step.getType();
             switch (type) {
                 case Integer:
-                    return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
-                                    : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
+                    return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.reuseNonShared)
+                                    : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.reuseNonShared);
                 case Double:
-                    return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
-                                    : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
+                    return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.reuseNonShared)
+                                    : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.reuseNonShared);
                 case Character:
                     return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
                                     : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
index 56374865240205f24e9b8a7a99656277ed34a29e..b0be4bf824b26e2a8147df4946a1ef51324462c2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
@@ -76,12 +76,12 @@ public final class PipelineBuilder {
     }
 
     public void appendAsVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) {
-        append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector));
+        append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector, false));
     }
 
     public void appendAsVector(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
         assert type == RType.Integer || type == RType.Double || type == RType.Complex || type == RType.Character || type == RType.Logical || type == RType.Raw;
-        append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true));
+        append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true, false));
     }
 
     public void appendNotNA(Object naReplacement, Message message, Object[] messageArgs) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
index 2ff5495c46850a8c5609786bf23324e65d99b800..cd0d124a10d0e064aa7f9a459cfe999da4f4e50c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
@@ -43,24 +44,18 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 public abstract class CastBaseNode extends CastNode {
 
-    protected static boolean isReusable(RAbstractVector v) {
-        if (v instanceof RSharingAttributeStorage) {
-            return !((RSharingAttributeStorage) v).isShared();
-        }
-        return false;
-    }
-
     private final BranchProfile listCoercionErrorBranch = BranchProfile.create();
     private final ConditionProfile hasDimNamesProfile = ConditionProfile.createBinaryProfile();
     private final NullProfile hasDimensionsProfile = NullProfile.create();
     private final NullProfile hasNamesProfile = NullProfile.create();
+    private final ValueProfile reuseClassProfile;
+
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
     @Child private GetDimAttributeNode getDimNode;
     @Child private SetDimNamesAttributeNode setDimNamesNode;
@@ -70,6 +65,9 @@ public abstract class CastBaseNode extends CastNode {
     private final boolean preserveDimensions;
     private final boolean preserveAttributes;
 
+    /** {@code true} if a cast should try to reuse a non-shared vector. */
+    private final boolean reuseNonShared;
+
     /**
      * GnuR provides several, sometimes incompatible, ways to coerce given value to given type. This
      * flag tells the cast node that it should behave in a way compatible with functions exposed by
@@ -82,6 +80,10 @@ public abstract class CastBaseNode extends CastNode {
     }
 
     protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
+        this(preserveNames, preserveDimensions, preserveAttributes, forRFFI, false);
+    }
+
+    protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean reuseNonShared) {
         this.preserveNames = preserveNames;
         this.preserveDimensions = preserveDimensions;
         this.preserveAttributes = preserveAttributes;
@@ -89,6 +91,8 @@ public abstract class CastBaseNode extends CastNode {
         if (preserveDimensions) {
             getDimNamesNode = GetDimNamesAttributeNode.create();
         }
+        this.reuseNonShared = reuseNonShared;
+        reuseClassProfile = reuseNonShared ? ValueProfile.createClassProfile() : null;
     }
 
     public final boolean preserveNames() {
@@ -107,6 +111,10 @@ public abstract class CastBaseNode extends CastNode {
         return preserveAttributes || preserveNames || preserveDimensions;
     }
 
+    public final boolean reuseNonShared() {
+        return reuseNonShared;
+    }
+
     protected abstract RType getTargetType();
 
     protected RError throwCannotCoerceListError(String type) {
@@ -174,4 +182,16 @@ public abstract class CastBaseNode extends CastNode {
         }
         return RNull.instance;
     }
+
+    protected boolean isReusable(RAbstractVector v) {
+        if (reuseNonShared && v instanceof RSharingAttributeStorage) {
+            return !((RSharingAttributeStorage) v).isShared();
+        }
+        return false;
+    }
+
+    protected RAbstractVector castWithReuse(RType targetType, RAbstractVector v, ConditionProfile naProfile) {
+        assert isReusable(v);
+        return reuseClassProfile.profile(v.castSafe(targetType, naProfile, preserveAttributes()));
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
index 9abeb67a8dbd105abcaf074d9907ab0aae07ff15..6fee221df0e9d383b8dad2318ddb419e0d958928 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
@@ -44,8 +44,8 @@ public abstract class CastDoubleBaseNode extends CastBaseNode {
         super(preserveNames, preserveDimensions, preserveAttributes);
     }
 
-    protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
-        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
+    protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean withReuse) {
+        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, withReuse);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
index 40e9f22fcd08fbf186ffa1ef1839447fb9eaf674..5f8e94ac36b35e1a6a6da06082760d7b82e10413 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
@@ -53,12 +53,12 @@ import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 @ImportStatic(RRuntime.class)
 public abstract class CastDoubleNode extends CastDoubleBaseNode {
 
-    protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
-        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
+    protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean withReuse) {
+        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, withReuse);
     }
 
     protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        super(preserveNames, preserveDimensions, preserveAttributes);
+        super(preserveNames, preserveDimensions, preserveAttributes, false, false);
     }
 
     @Child private CastDoubleNode recursiveCastDouble;
@@ -66,7 +66,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
     private Object castDoubleRecursive(Object o) {
         if (recursiveCastDouble == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastDouble = insert(CastDoubleNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes()));
+            recursiveCastDouble = insert(CastDoubleNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes(), false, reuseNonShared()));
         }
         return recursiveCastDouble.executeDouble(o);
     }
@@ -92,14 +92,29 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
         return vectorCopy(operand, ddata, !seenNA);
     }
 
+    @Specialization(guards = "isReusable(operand)")
+    protected RAbstractDoubleVector doIntVectorReuse(RAbstractIntVector operand) {
+        return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile());
+    }
+
+    @Specialization(guards = "isReusable(operand)")
+    protected RAbstractDoubleVector doLogicalVectorDimsReuse(RAbstractLogicalVector operand) {
+        return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile());
+    }
+
+    @Specialization(guards = "isReusable(operand)")
+    protected RAbstractDoubleVector doRawVectorReuse(RRawVector operand) {
+        return (RAbstractDoubleVector) castWithReuse(RType.Double, operand, naProfile.getConditionProfile());
+    }
+
     @Specialization
-    protected RAbstractDoubleVector doIntVector(RAbstractIntVector operand) {
-        return castWithReuse(operand, index -> naCheck.convertIntToDouble(operand.getDataAt(index)));
+    protected RDoubleVector doIntVector(RAbstractIntVector operand) {
+        return createResultVector(operand, index -> naCheck.convertIntToDouble(operand.getDataAt(index)));
     }
 
     @Specialization
-    protected RAbstractDoubleVector doLogicalVectorDims(RAbstractLogicalVector operand) {
-        return castWithReuse(operand, index -> naCheck.convertLogicalToDouble(operand.getDataAt(index)));
+    protected RDoubleVector doLogicalVectorDims(RAbstractLogicalVector operand) {
+        return createResultVector(operand, index -> naCheck.convertLogicalToDouble(operand.getDataAt(index)));
     }
 
     @Specialization
@@ -158,8 +173,8 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
     }
 
     @Specialization
-    protected RAbstractDoubleVector doRawVector(RRawVector operand) {
-        return castWithReuse(operand, index -> RRuntime.raw2double(operand.getDataAt(index)));
+    protected RDoubleVector doRawVector(RRawVector operand) {
+        return createResultVector(operand, index -> RRuntime.raw2double(operand.getDataAt(index)));
     }
 
     @Specialization
@@ -223,23 +238,20 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
         throw error(RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "vector");
     }
 
-    private RAbstractDoubleVector castWithReuse(RAbstractVector v, IntToDoubleFunction elementFunction) {
-        if (isReusable(v)) {
-            return (RAbstractDoubleVector) v.castSafe(RType.Double, naProfile.getConditionProfile(), preserveAttributes());
-        }
-        return createResultVector(v, elementFunction);
+    public static CastDoubleNode create() {
+        return CastDoubleNodeGen.create(true, true, true, false, false);
     }
 
-    public static CastDoubleNode create() {
-        return CastDoubleNodeGen.create(true, true, true);
+    public static CastDoubleNode createWithReuse() {
+        return CastDoubleNodeGen.create(true, true, true, false, true);
     }
 
     public static CastDoubleNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        return CastDoubleNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true);
+        return CastDoubleNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true, false);
     }
 
     public static CastDoubleNode createNonPreserving() {
-        return CastDoubleNodeGen.create(false, false, false);
+        return CastDoubleNodeGen.create(false, false, false, false, false);
     }
 
     protected ForeignArray2R createForeignArray2RNode() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
index 18c5757508adf68eee8a90bbba2db0354c08867f..10e420d5b12078a830e6c6190c09a515eecfc7f2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
@@ -41,12 +41,12 @@ public abstract class CastIntegerBaseNode extends CastBaseNode {
 
     @Child private CastIntegerNode recursiveCastInteger;
 
-    protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
-        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
+    protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean withReuse) {
+        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, withReuse);
     }
 
     protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        super(preserveNames, preserveDimensions, preserveAttributes);
+        super(preserveNames, preserveDimensions, preserveAttributes, false, false);
     }
 
     @Override
@@ -57,7 +57,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode {
     protected Object castIntegerRecursive(Object o) {
         if (recursiveCastInteger == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes()));
+            recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes(), false, reuseNonShared()));
         }
         return recursiveCastInteger.executeInt(o);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
index 0d7552c06cbfc48169550d8b35dc1d91f002a01c..997193d66f30f27c89311fbdcccac51030e7012c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
@@ -57,12 +57,12 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
 
     private final BranchProfile warningBranch = BranchProfile.create();
 
-    protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
-        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
+    protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean withReuse) {
+        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, withReuse);
     }
 
     protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        super(preserveNames, preserveDimensions, preserveAttributes);
+        super(preserveNames, preserveDimensions, preserveAttributes, false, false);
     }
 
     public abstract Object executeInt(int o);
@@ -160,19 +160,34 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
         return vectorCopy(operand, idata, !seenNA);
     }
 
+    @Specialization(guards = "isReusable(operand)")
+    public RAbstractIntVector doLogicalVectorReuse(RAbstractLogicalVector operand) {
+        return (RAbstractIntVector) castWithReuse(RType.Integer, operand, naProfile.getConditionProfile());
+    }
+
+    @Specialization(guards = "isReusable(operand)")
+    protected RAbstractIntVector doDoubleVectorReuse(RAbstractDoubleVector operand) {
+        return (RAbstractIntVector) castWithReuse(RType.Integer, operand, naProfile.getConditionProfile());
+    }
+
+    @Specialization(guards = "isReusable(operand)")
+    protected RAbstractIntVector doRawVectorReuse(RAbstractRawVector operand) {
+        return (RAbstractIntVector) castWithReuse(RType.Integer, operand, naProfile.getConditionProfile());
+    }
+
     @Specialization
-    public RAbstractIntVector doLogicalVector(RAbstractLogicalVector operand) {
-        return castWithReuse(operand, index -> naCheck.convertLogicalToInt(operand.getDataAt(index)));
+    public RIntVector doLogicalVector(RAbstractLogicalVector operand) {
+        return createResultVector(operand, index -> naCheck.convertLogicalToInt(operand.getDataAt(index)));
     }
 
     @Specialization
-    protected RAbstractIntVector doDoubleVector(RAbstractDoubleVector operand) {
-        return castWithReuse(operand, index -> naCheck.convertDoubleToInt(operand.getDataAt(index)));
+    protected RIntVector doDoubleVector(RAbstractDoubleVector operand) {
+        return createResultVector(operand, index -> naCheck.convertDoubleToInt(operand.getDataAt(index)));
     }
 
     @Specialization
-    protected RAbstractIntVector doRawVector(RAbstractRawVector operand) {
-        return castWithReuse(operand, index -> RRuntime.raw2int(operand.getDataAt(index)));
+    protected RIntVector doRawVector(RAbstractRawVector operand) {
+        return createResultVector(operand, index -> RRuntime.raw2int(operand.getDataAt(index)));
     }
 
     @Specialization
@@ -241,23 +256,20 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
         return arg instanceof RIntVector;
     }
 
-    private RAbstractIntVector castWithReuse(RAbstractVector v, IntToIntFunction elementFunction) {
-        if (isReusable(v)) {
-            return (RAbstractIntVector) v.castSafe(RType.Integer, naProfile.getConditionProfile(), preserveAttributes());
-        }
-        return createResultVector(v, elementFunction);
+    public static CastIntegerNode create() {
+        return CastIntegerNodeGen.create(true, true, true, false, false);
     }
 
-    public static CastIntegerNode create() {
-        return CastIntegerNodeGen.create(true, true, true);
+    public static CastIntegerNode createWithReuse() {
+        return CastIntegerNodeGen.create(true, true, true, false, true);
     }
 
     public static CastIntegerNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        return CastIntegerNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true);
+        return CastIntegerNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true, false);
     }
 
     public static CastIntegerNode createNonPreserving() {
-        return CastIntegerNodeGen.create(false, false, false);
+        return CastIntegerNodeGen.create(false, false, false, false, false);
     }
 
     protected ForeignArray2R createForeignArray2RNode() {