diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index bd7f56a661f746b98a2bfa1689381bfd7778fef1..ee74036ba299c2a123f3cd6a74c7fdc23a9f8bf4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -307,49 +307,90 @@ public abstract class ExtractVectorNode extends RBaseNode {
         }
     }
 
-    protected static ReadElementNode createReadElement() {
+    static ReadElementNode createReadElement() {
         return new ReadElementNode();
     }
 
-    static final class ReadElementNode extends RBaseNode {
+    abstract static class AccessElementNode extends RBaseNode {
 
-        @Child private Node foreignRead = com.oracle.truffle.api.interop.Message.READ.createNode();
-        @Child private Node keyInfoNode = com.oracle.truffle.api.interop.Message.KEY_INFO.createNode();
-        @Child private Node hasSizeNode = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode();
-        @Child private CastStringNode castNode = CastStringNode.create();
-        @Child private FirstStringNode firstString = createFirstString();
+        @Child private Node hasSizeNode;
+        @Child private CastStringNode castNode;
+        @Child private FirstStringNode firstString;
 
         private final ConditionProfile isIntProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile isDoubleProfile = ConditionProfile.createBinaryProfile();
 
-        public Object execute(Object position, TruffleObject object) throws InteropException {
+        protected final Object extractPosition(Object position) {
             Object pos = position;
             if (isIntProfile.profile(pos instanceof Integer)) {
                 pos = ((int) pos) - 1;
             } else if (isDoubleProfile.profile(pos instanceof Double)) {
                 pos = ((double) pos) - 1;
             } else if (pos instanceof RAbstractDoubleVector) {
-                pos = ((RAbstractDoubleVector) pos).getDataAt(0) - 1;
+                RAbstractDoubleVector vector = (RAbstractDoubleVector) pos;
+                if (vector.getLength() == 0) {
+                    throw error(RError.Message.GENERIC, "invalid index during foreign access");
+                }
+                pos = vector.getDataAt(0) - 1;
             } else if (pos instanceof RAbstractIntVector) {
-                pos = ((RAbstractIntVector) pos).getDataAt(0) - 1;
+                RAbstractIntVector vector = (RAbstractIntVector) pos;
+                if (vector.getLength() == 0) {
+                    throw error(RError.Message.GENERIC, "invalid index during foreign access");
+                }
+                pos = vector.getDataAt(0) - 1;
             } else if (pos instanceof RAbstractStringVector) {
+                if (castNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    castNode = insert(CastStringNode.create());
+                }
+                if (firstString == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    firstString = insert(createFirstString());
+                }
                 pos = firstString.executeString(castNode.doCast(pos));
             } else if (!(pos instanceof String)) {
                 throw error(RError.Message.GENERIC, "invalid index during foreign access");
             }
+            return pos;
+        }
 
+        protected final boolean hasSize(TruffleObject object) {
+            if (hasSizeNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                hasSizeNode = insert(com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode());
+            }
+            return ForeignAccess.sendHasSize(hasSizeNode, object);
+        }
+    }
+
+    static final class ReadElementNode extends AccessElementNode {
+
+        @Child private Node foreignRead = com.oracle.truffle.api.interop.Message.READ.createNode();
+        @Child private Node classForeignRead;
+        @Child private Node keyInfoNode;
+
+        public Object execute(Object position, TruffleObject object) throws InteropException {
+            Object pos = extractPosition(position);
+            if (keyInfoNode == null) {
+                try {
+                    return ForeignAccess.sendRead(foreignRead, object, pos);
+                } catch (InteropException e) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    keyInfoNode = insert(com.oracle.truffle.api.interop.Message.KEY_INFO.createNode());
+                }
+            }
             int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, pos);
-            if (KeyInfo.isReadable(info) || ForeignAccess.sendHasSize(hasSizeNode, object)) {
+            if (KeyInfo.isReadable(info) || hasSize(object)) {
                 return ForeignAccess.sendRead(foreignRead, object, pos);
             } else if (pos instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
-                TruffleObject clazz = toJavaClass(object);
-                info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, pos);
-                if (KeyInfo.isReadable(info)) {
-                    return ForeignAccess.sendRead(foreignRead, clazz, pos);
+                if (classForeignRead == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    classForeignRead = insert(com.oracle.truffle.api.interop.Message.READ.createNode());
                 }
+                return ForeignAccess.sendRead(classForeignRead, toJavaClass(object), pos);
             }
+            CompilerDirectives.transferToInterpreter();
             throw error(RError.Message.GENERIC, "invalid index/identifier during foreign access: " + pos);
-
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
index 7c9a69fd4becbae952b07825bd1ffae34f93574a..86bfe74041bc4c902f63d135acd8d3261005a66c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode.AccessElementNode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode.ExtractSingleName;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode.ReadElementNode;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
@@ -44,7 +44,6 @@ import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.objects.GetS4DataSlot;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
-import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.FirstStringNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -61,10 +60,7 @@ import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RScalarVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 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.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
@@ -304,48 +300,38 @@ public abstract class ReplaceVectorNode extends RBaseNode {
         return new WriteElementNode();
     }
 
-    static final class WriteElementNode extends RBaseNode {
+    static final class WriteElementNode extends AccessElementNode {
 
-        @Child private Node keyInfoNode = com.oracle.truffle.api.interop.Message.KEY_INFO.createNode();
-        @Child private Node hasSizeNode = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode();
+        @Child private Node keyInfoNode;
         @Child private Node foreignWrite = com.oracle.truffle.api.interop.Message.WRITE.createNode();
+        @Child private Node classForeignWrite;
         @Child private R2Foreign r2Foreign = R2Foreign.create();
-        @Child private CastStringNode castNode = CastStringNode.create();
-        @Child private FirstStringNode firstString = ExtractVectorNode.createFirstString();
-
-        private final ConditionProfile isIntProfile = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile isDoubleProfile = ConditionProfile.createBinaryProfile();
 
         private void execute(Object position, TruffleObject object, Object writtenValue) throws InteropException {
-            Object pos = position;
-            if (isIntProfile.profile(pos instanceof Integer)) {
-                pos = ((int) pos) - 1;
-            } else if (isDoubleProfile.profile(pos instanceof Double)) {
-                pos = ((double) pos) - 1;
-            } else if (pos instanceof RAbstractDoubleVector) {
-                pos = ((RAbstractDoubleVector) pos).getDataAt(0) - 1;
-            } else if (pos instanceof RAbstractIntVector) {
-                pos = ((RAbstractIntVector) pos).getDataAt(0) - 1;
-            } else if (pos instanceof RAbstractStringVector) {
-                String string = firstString.executeString(castNode.doCast(pos));
-                pos = string;
-            } else if (!(pos instanceof String)) {
-                throw error(RError.Message.GENERIC, "invalid index during foreign access");
+            Object pos = extractPosition(position);
+            Object value = r2Foreign.execute(writtenValue);
+            if (keyInfoNode == null) {
+                try {
+                    ForeignAccess.sendWrite(foreignWrite, object, pos, value);
+                    return;
+                } catch (InteropException e) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    keyInfoNode = insert(com.oracle.truffle.api.interop.Message.KEY_INFO.createNode());
+                }
             }
-
             int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, pos);
-            if (KeyInfo.isWritable(info) || ForeignAccess.sendHasSize(hasSizeNode, object) ||
-                            (pos instanceof String && !JavaInterop.isJavaObject(Object.class, object))) {
-                ForeignAccess.sendWrite(foreignWrite, object, pos, r2Foreign.execute(writtenValue));
+            if (KeyInfo.isWritable(info) || hasSize(object)) {
+                ForeignAccess.sendWrite(foreignWrite, object, pos, value);
                 return;
             } else if (pos instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
-                TruffleObject clazz = toJavaClass(object);
-                info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, pos);
-                if (KeyInfo.isWritable(info)) {
-                    ForeignAccess.sendWrite(foreignWrite, clazz, pos, r2Foreign.execute(writtenValue));
-                    return;
+                if (classForeignWrite == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    classForeignWrite = insert(com.oracle.truffle.api.interop.Message.WRITE.createNode());
                 }
+                ForeignAccess.sendWrite(classForeignWrite, toJavaClass(object), pos, value);
+                return;
             }
+            CompilerDirectives.transferToInterpreter();
             throw error(RError.Message.GENERIC, "invalid index/identifier during foreign access: " + pos);
         }
     }