diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
index b945b240a632d3354d46a864d80ba6c83f3d4cfd..3dc6a3207c656f8f9fd63f32780bd86192b3f97a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RDeparse;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -50,7 +51,7 @@ public abstract class AsCharacter extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(AsCharacter.class);
-        casts.arg("x").returnIf(missingValue().or(nullValue()), emptyStringVector()).mapIf(instanceOf(RAbstractListVector.class).not(), asStringVector());
+        casts.arg("x").defaultWarningContext(RError.NO_CALLER).returnIf(missingValue().or(nullValue()), emptyStringVector()).mapIf(instanceOf(RAbstractListVector.class).not(), asStringVector());
     }
 
     @Specialization(guards = "reuseTemporaryNode.supports(v)", limit = "getVectorAccessCacheSize()")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/MatchInternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/MatchInternalNode.java
index be17acf17cd76042091b6b6457a4d11871a6d95d..998ea0057699a111d243471fc0ae03c025e95a30 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/MatchInternalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/MatchInternalNode.java
@@ -64,7 +64,7 @@ public abstract class MatchInternalNode extends RBaseNode {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castString = insert(CastStringNodeGen.create(false, false, false));
         }
-        return (RAbstractStringVector) castString.doCast(operand);
+        return (RAbstractStringVector) RRuntime.asAbstractVector(castString.doCast(operand));
     }
 
     protected boolean isSequence(RAbstractVector vec) {
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 198ee3b003554aba713b10fb3da6db947fe56e3f..7c8a2db5b90a8d2364f7d1a49de2aeabe79cedbc 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
@@ -240,8 +240,8 @@ public final class PipelineToCastNode {
                     return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure)
                                     : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, step.useClosure);
                 case Character:
-                    return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
-                                    : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
+                    return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, false, warningContext)
+                                    : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, false, false, warningContext);
                 case Logical:
                     return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
                                     : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java
index 74fe4684bf3321d87b4433281ba4ef18dfe1b287..59fd9a9746746841190b0139b3b926f2db832808 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringBaseNode.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RMissing;
@@ -41,6 +42,10 @@ public abstract class CastStringBaseNode extends CastBaseNode {
         super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
     }
 
+    protected CastStringBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure, ErrorContext warningContext) {
+        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure, warningContext);
+    }
+
     @Override
     protected final RType getTargetType() {
         return RType.Character;
@@ -71,7 +76,7 @@ public abstract class CastStringBaseNode extends CastBaseNode {
     }
 
     @Specialization
-    protected String doRaw(RComplex value) {
+    protected String doComplex(RComplex value) {
         return toString(value);
     }
 
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 27237af6ec3077967c10ccfefec6b3f84f23b722..7dc6274f0be7b3becf98a7185608cb2a66bb8e22 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
@@ -29,8 +29,10 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.runtime.DSLConfig;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RForeignBooleanWrapper;
 import com.oracle.truffle.r.runtime.data.RForeignDoubleWrapper;
@@ -42,11 +44,14 @@ import com.oracle.truffle.r.runtime.data.RStringSequence;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.closures.RClosures;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
 import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 
-@ImportStatic(RRuntime.class)
+@ImportStatic({RRuntime.class, DSLConfig.class})
 public abstract class CastStringNode extends CastStringBaseNode {
 
     @Child private CastStringNode recursiveCastString;
@@ -59,6 +64,10 @@ public abstract class CastStringNode extends CastStringBaseNode {
         super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
     }
 
+    protected CastStringNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, boolean useClosure, ErrorContext warningContext) {
+        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI, useClosure, warningContext);
+    }
+
     public abstract Object executeString(int o);
 
     public abstract Object executeString(double o);
@@ -75,10 +84,6 @@ public abstract class CastStringNode extends CastStringBaseNode {
         return ret;
     }
 
-    protected boolean isIntSequence(RAbstractContainer c) {
-        return c instanceof RIntSequence;
-    }
-
     @Specialization
     protected RAbstractStringVector doStringVector(RAbstractStringVector vector) {
         return vector;
@@ -89,24 +94,57 @@ public abstract class CastStringNode extends CastStringBaseNode {
         return factory().createStringSequence("", "", vector.getStart(), vector.getStride(), vector.getLength());
     }
 
-    @Specialization(guards = {"!isIntSequence(operandIn)", "!isRAbstractStringVector(operandIn)", "!isForeignWrapper(operandIn)"})
-    protected RStringVector doAbstractContainer(RAbstractContainer operandIn,
+    @Specialization(guards = {"uAccess.supports(operandIn)", "handleAsAtomic(operandIn)"}, limit = "getGenericVectorAccessCacheSize()")
+    protected RStringVector doAbstractAtomicVector(RAbstractAtomicVector operandIn,
                     @Cached("createClassProfile()") ValueProfile operandProfile,
-                    @Cached("createBinaryProfile()") ConditionProfile isLanguageProfile) {
+                    @Cached("operandIn.access()") VectorAccess uAccess) {
         RAbstractContainer operand = operandProfile.profile(operandIn);
         String[] sdata = new String[operand.getLength()];
-        // conversions to character will not introduce new NAs
-        for (int i = 0; i < operand.getLength(); i++) {
-            Object o = operand.getDataAtAsObject(i);
-            if (isLanguageProfile.profile((o instanceof RPairList && ((RPairList) o).isLanguage()))) {
-                sdata[i] = RDeparse.deparse(o);
-            } else {
-                sdata[i] = toString(o);
+        // conversions to character will not introduce new NAs,
+        // but lets pass the warning context anyway
+        try (VectorAccess.SequentialIterator sIter = uAccess.access(operand, warningContext())) {
+            while (uAccess.next(sIter)) {
+                int i = sIter.getIndex();
+                sdata[i] = uAccess.getString(sIter);
+            }
+        }
+        return vectorCopy(operand, sdata);
+    }
+
+    @Specialization(replaces = "doAbstractAtomicVector", guards = "handleAsAtomic(operandIn)")
+    protected RStringVector doAbstractAtomicVectorGeneric(RAbstractAtomicVector operandIn,
+                    @Cached("createClassProfile()") ValueProfile operandProfile) {
+        return doAbstractAtomicVector(operandIn, operandProfile, operandIn.slowPathAccess());
+    }
+
+    @Specialization(guards = {"uAccess.supports(x)", "handleAsNonAtomic(x)"}, limit = "getGenericVectorAccessCacheSize()")
+    protected RStringVector doNonAtomic(RAbstractContainer x,
+                    @Cached("createClassProfile()") ValueProfile operandProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile isLanguageProfile,
+                    @Cached("x.access()") VectorAccess uAccess) {
+        RAbstractContainer operand = operandProfile.profile(x);
+        String[] sdata = new String[operand.getLength()];
+        try (VectorAccess.SequentialIterator sIter = uAccess.access(operand, warningContext())) {
+            while (uAccess.next(sIter)) {
+                int i = sIter.getIndex();
+                Object o = uAccess.getListElement(sIter);
+                if (isLanguageProfile.profile((o instanceof RPairList && ((RPairList) o).isLanguage()))) {
+                    sdata[i] = RDeparse.deparse(o);
+                } else {
+                    sdata[i] = toString(o);
+                }
             }
         }
         return vectorCopy(operand, sdata);
     }
 
+    @Specialization(replaces = "doNonAtomic", guards = "handleAsNonAtomic(list)")
+    protected RStringVector doNonAtomicGeneric(RAbstractListVector list,
+                    @Cached("createClassProfile()") ValueProfile operandProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile isLanguageProfile) {
+        return doNonAtomic(list, operandProfile, isLanguageProfile, list.slowPathAccess());
+    }
+
     @Specialization(guards = "isForeignObject(obj)")
     protected RAbstractStringVector doForeignObject(TruffleObject obj,
                     @Cached("create()") ForeignArray2R foreignArray2R) {
@@ -128,10 +166,6 @@ public abstract class CastStringNode extends CastStringBaseNode {
         return s.getName();
     }
 
-    protected boolean isForeignWrapper(Object value) {
-        return value instanceof RForeignWrapper;
-    }
-
     @Specialization
     protected RAbstractStringVector doForeignWrapper(RForeignBooleanWrapper operand) {
         return RClosures.createToStringVector(operand, true);
@@ -147,6 +181,22 @@ public abstract class CastStringNode extends CastStringBaseNode {
         return RClosures.createToStringVector(operand, true);
     }
 
+    protected boolean isForeignWrapper(Object value) {
+        return value instanceof RForeignWrapper;
+    }
+
+    protected boolean isIntSequence(RAbstractContainer c) {
+        return c instanceof RIntSequence;
+    }
+
+    protected boolean handleAsAtomic(RAbstractAtomicVector x) {
+        return !isForeignWrapper(x) && !(x instanceof RIntSequence || x instanceof RAbstractStringVector);
+    }
+
+    protected boolean handleAsNonAtomic(RAbstractContainer x) {
+        return !isForeignWrapper(x) && !(x instanceof RAbstractAtomicVector);
+    }
+
     public static CastStringNode create() {
         return CastStringNodeGen.create(true, true, true);
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 84853d8c5effef726e1d85bc70526307c8bd5af1..90ba93d5263ffe1a41a2d0d5d3be49392e4d2313 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -6087,6 +6087,10 @@ character(0)
 #{ as.character(1) }
 [1] "1"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter#
+#{ as.character(1.1:3.1) }
+[1] "1.1" "2.1" "3.1"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter#
 #{ as.character(1:3) }
 [1] "1" "2" "3"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
index ddab265dc9a62945bf2436cd73fe2cac41dacae8..6e399a441abd6d4f46051720d2ed0de86bbe484e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
@@ -264,6 +264,7 @@ public class TestBuiltin_ascharacter extends TestBase {
         assertEval("{ as.character(1L) }");
         assertEval("{ as.character(TRUE) }");
         assertEval("{ as.character(1:3) }");
+        assertEval("{ as.character(1.1:3.1) }");
         assertEval("{ as.character(NULL) }");
 
         assertEval("{ as.character(list(1,2,3)) }");