diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index eadcc67c1691925fac1754d3f54317dbf876dcd6..f25b9edc617ed3520201d395dbc3574a5ad23c2c 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -38,23 +38,18 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.impl.FindContextNode;
-import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactory;
-import com.oracle.truffle.r.engine.interop.RFunctionAccessFactory;
-import com.oracle.truffle.r.engine.interop.RListAccessFactory;
 import com.oracle.truffle.r.library.graphics.RGraphics;
 import com.oracle.truffle.r.nodes.RASTBuilder;
 import com.oracle.truffle.r.nodes.RASTUtils;
@@ -93,7 +88,6 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
@@ -620,22 +614,4 @@ final class REngine implements Engine, Engine.Timings {
     private static Object evaluatePromise(Object value) {
         return value instanceof RPromise ? PromiseHelperNode.evaluateSlowPath(null, (RPromise) value) : value;
     }
-
-    @Override
-    public Class<? extends TruffleLanguage<RContext>> getTruffleLanguage() {
-        return TruffleRLanguage.class;
-    }
-
-    @Override
-    public ForeignAccess getForeignAccess(RTypedValue value) {
-        if (value instanceof RList) {
-            return ForeignAccess.create(RList.class, new RListAccessFactory());
-        } else if (value instanceof RAbstractVector) {
-            return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
-        } else if (value instanceof RFunction) {
-            return ForeignAccess.create(RFunction.class, new RFunctionAccessFactory());
-        } else {
-            throw RInternalError.shouldNotReachHere("cannot create ForeignAccess for " + value);
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
index 0182f25bda731f5c77a100e0b00c39619d004891..ce068b4847c71392daa929cef73bb9268bd43d51 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.engine;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.util.Locale;
 
@@ -33,6 +34,7 @@ import com.oracle.truffle.api.instrumentation.ProvidedTags;
 import com.oracle.truffle.api.instrumentation.StandardTags;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.r.engine.interop.RForeignAccessFactoryImpl;
 import com.oracle.truffle.r.nodes.RASTBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinPackages;
 import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags;
@@ -72,7 +74,7 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
             RVersionInfo.initialize();
             TempPathName.initialize();
             RPackageSource.initialize();
-            RContext.initialize(new RASTBuilder(), new RRuntimeASTAccessImpl(), RBuiltinPackages.getInstance());
+            RContext.initialize(new RASTBuilder(), new RRuntimeASTAccessImpl(), RBuiltinPackages.getInstance(), new RForeignAccessFactoryImpl());
         } catch (Throwable t) {
             System.out.println("error during engine initialization:");
             t.printStackTrace();
@@ -119,22 +121,25 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
     }
 
     @Override
+    @SuppressWarnings("try")
     protected CallTarget parse(Source source, Node context, String... argumentNames) throws IOException {
-        try {
-            return RContext.getEngine().parseToCallTarget(source);
-        } catch (IncompleteSourceException e) {
-            throw new com.oracle.truffle.api.vm.IncompleteSourceException(e);
-        } catch (ParseException e) {
-            return new CallTarget() {
-                @Override
-                public Object call(Object... arguments) {
-                    try {
-                        throw e.throwAsRError();
-                    } catch (@SuppressWarnings("hiding") RError e) {
-                        return null;
+        try (Closeable c = RContext.withinContext(findContext(createFindContextNode()))) {
+            try {
+                return RContext.getEngine().parseToCallTarget(source);
+            } catch (IncompleteSourceException e) {
+                throw new com.oracle.truffle.api.vm.IncompleteSourceException(e);
+            } catch (ParseException e) {
+                return new CallTarget() {
+                    @Override
+                    public Object call(Object... arguments) {
+                        try {
+                            throw e.throwAsRError();
+                        } catch (@SuppressWarnings("hiding") RError e) {
+                            return null;
+                        }
                     }
-                }
-            };
+                };
+            }
         }
     }
 
@@ -150,10 +155,14 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
     }
 
     // TODO: why isn't the original method public?
-    Node actuallyCreateFindContextNode() {
+    public Node actuallyCreateFindContextNode() {
         return createFindContextNode();
     }
 
+    public RContext actuallyFindContext0(Node contextNode) {
+        return findContext(contextNode);
+    }
+
     @Override
     protected Object evalInContext(Source source, Node node, MaterializedFrame frame) throws IOException {
         return RContext.getEngine().parseAndEval(source, frame, false);
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ccbe72fabd3e1d07058684166c9696d07065dd9
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RForeignAccessFactory;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
+
+    @Override
+    public ForeignAccess getForeignAccess(RTypedValue value) {
+        if (value instanceof RList) {
+            return ForeignAccess.create(RList.class, new RListAccessFactory());
+        } else if (value instanceof RAbstractVector) {
+            return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
+        } else if (value instanceof RFunction) {
+            return ForeignAccess.create(RFunction.class, new RFunctionAccessFactory());
+        } else {
+            throw RInternalError.shouldNotReachHere("cannot create ForeignAccess for " + value);
+        }
+    }
+
+    @Override
+    public Class<? extends TruffleLanguage<RContext>> getTruffleLanguage() {
+        return TruffleRLanguage.class;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropExecuteNode.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropExecuteNode.java
index 5bf61dfa52b1f88e09af93b8b802bfd6bf3fe778..c0ba64a4b7892861ef69a5b26f97c09dd64308bd 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropExecuteNode.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropExecuteNode.java
@@ -22,24 +22,37 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.util.List;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.r.nodes.function.CallMatcherNode;
+import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RFunction;
 
 class RInteropExecuteNode extends RootNode {
 
-    private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor();
+    private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor("R interop frame");
+    private final Object argsIdentifier = new Object();
+    private final FrameSlot slot = emptyFrameDescriptor.addFrameSlot(argsIdentifier, FrameSlotKind.Object);
 
+    @Child private RCallNode call = RCallNode.createExplicitCall(argsIdentifier);
     @Child private CallMatcherNode callMatcher = CallMatcherNode.create(false, true);
+    @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
     private final ArgumentsSignature suppliedSignature;
 
@@ -49,6 +62,7 @@ class RInteropExecuteNode extends RootNode {
     }
 
     @Override
+    @SuppressWarnings("try")
     public Object execute(VirtualFrame frame) {
         RFunction function = (RFunction) ForeignAccess.getReceiver(frame);
         List<Object> arguments = ForeignAccess.getArguments(frame);
@@ -56,6 +70,13 @@ class RInteropExecuteNode extends RootNode {
         Object[] dummyFrameArgs = RArguments.createUnitialized();
         VirtualFrame dummyFrame = Truffle.getRuntime().createVirtualFrame(dummyFrameArgs, emptyFrameDescriptor);
 
-        return callMatcher.execute(dummyFrame, suppliedSignature, arguments.toArray(), function, null, null);
+        RArgsValuesAndNames actualArgs = new RArgsValuesAndNames(arguments.toArray(), suppliedSignature);
+        dummyFrame.setObject(slot, actualArgs);
+        try (Closeable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+            return call.execute(dummyFrame, function);
+        } catch (IOException e) {
+            CompilerDirectives.transferToInterpreter();
+            throw new RuntimeException(e);
+        }
     }
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
index 4de365306695b4327d7deab5d35287942063148e..b2fe0c289a40aea1203244bf285887efcbc14264 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -81,8 +81,9 @@ static jmethodID Rf_PairToVectorListMethodID;
 static jmethodID gnuRCodeForObjectMethodID;
 static jmethodID NAMED_MethodID;
 static jmethodID TYPEOF_MethodID;
+static jmethodID OBJECT_MethodID;
 static jmethodID DUPLICATE_ATTRIB_MethodID;
-static jmethodID iS4ObjectMethodID;
+static jmethodID isS4ObjectMethodID;
 static jmethodID logObject_MethodID;
 
 static jclass RExternalPtrClass;
@@ -157,8 +158,9 @@ void init_internals(JNIEnv *env) {
 	Rf_PairToVectorListMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_PairToVectorList", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
 	NAMED_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "NAMED", "(Ljava/lang/Object;)I", 1);
 	TYPEOF_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "TYPEOF", "(Ljava/lang/Object;)I", 1);
+	OBJECT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "OBJECT", "(Ljava/lang/Object;)I", 1);
 	DUPLICATE_ATTRIB_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "DUPLICATE_ATTRIB", "(Ljava/lang/Object;Ljava/lang/Object;)V", 1);
-	iS4ObjectMethodID = checkGetMethodID(env, CallRFFIHelperClass, "isS4Object", "(Ljava/lang/Object;)I", 1);
+	isS4ObjectMethodID = checkGetMethodID(env, CallRFFIHelperClass, "isS4Object", "(Ljava/lang/Object;)I", 1);
 	logObject_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "logObject", "(Ljava/lang/Object;)V", 1);
 
 	RExternalPtrClass = checkFindClass(env, "com/oracle/truffle/r/runtime/data/RExternalPtr");
@@ -1171,8 +1173,8 @@ SEXP ATTRIB(SEXP x){
 }
 
 int OBJECT(SEXP x){
-    unimplemented("OBJECT");
-    return 0;
+	JNIEnv *env = getEnv();
+	return 	(*env)->CallStaticIntMethod(env, CallRFFIHelperClass, OBJECT_MethodID, x);
 }
 
 int MARK(SEXP x){
@@ -1251,7 +1253,7 @@ R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
 
 int IS_S4_OBJECT(SEXP x) {
 	JNIEnv *env = getEnv();
-	return 	(*env)->CallStaticIntMethod(env, CallRFFIHelperClass, iS4ObjectMethodID, x);
+	return 	(*env)->CallStaticIntMethod(env, CallRFFIHelperClass, isS4ObjectMethodID, x);
 }
 
 void SET_S4_OBJECT(SEXP x) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index 638946ec8596417fb0afe0821ac21d12d83301ee..d7d74400b22f6ae104736911fcec886318b2df5d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -122,7 +122,7 @@ public abstract class UpdateAttr extends RInvisibleBuiltinNode {
     protected RAbstractContainer updateAttr(RAbstractContainer container, String name, RNull value) {
         controlVisibility();
         String internedName = intern(name);
-        RAbstractContainer result = container.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
         // the name is interned, so identity comparison is sufficient
         if (internedName == RRuntime.DIM_ATTR_KEY) {
             result.setDimensions(null);
@@ -155,7 +155,7 @@ public abstract class UpdateAttr extends RInvisibleBuiltinNode {
     protected RAbstractContainer updateAttr(RAbstractContainer container, String name, Object value) {
         controlVisibility();
         String internedName = intern(name);
-        RAbstractContainer result = container.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
         // the name is interned, so identity comparison is sufficient
         if (internedName == RRuntime.DIM_ATTR_KEY) {
             RAbstractIntVector dimsVector = castInteger(castVector(value));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index b17d4c24aac84d5887b291b9486ecd50d9ac9a0f..90d04224e4413df45ebde4009b277f9124aa4df3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -98,7 +98,7 @@ public abstract class UpdateAttributes extends RInvisibleBuiltinNode {
     @Specialization
     protected RAbstractVector updateAttributes(RAbstractVector abstractVector, @SuppressWarnings("unused") RNull list) {
         controlVisibility();
-        RAbstractVector resultVector = (RAbstractVector) abstractVector.materializeNonShared();
+        RAbstractVector resultVector = (RAbstractVector) abstractVector.getNonShared();
         resultVector.resetAllAttributes(true);
         return resultVector;
     }
@@ -111,7 +111,7 @@ public abstract class UpdateAttributes extends RInvisibleBuiltinNode {
             throw RError.error(this, RError.Message.ATTRIBUTES_NAMED);
         }
         RStringVector listNames = (RStringVector) listNamesObject;
-        RAbstractContainer result = container.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
         if (numAttributesProfile.profile(list.getLength() == 0)) {
             result.resetAllAttributes(true);
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
index cd33324c69dc387941c29c28280a7709d5cd0b78..518f22a57ccb58a104092a5d3eb3e2cf588c540f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
@@ -76,7 +76,7 @@ public abstract class UpdateClass extends RBuiltinNode {
     protected Object setClass(RAbstractContainer arg, @SuppressWarnings("unused") RNull className) {
         controlVisibility();
 
-        RAbstractContainer result = arg.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) arg.getNonShared();
         return result.setClassAttr(null, false);
     }
 
@@ -111,7 +111,7 @@ public abstract class UpdateClass extends RBuiltinNode {
                 return setClass((RAbstractVector) result, RNull.instance);
             }
         }
-        RAbstractContainer result = arg.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) arg.getNonShared();
         if (result instanceof RAbstractVector) {
             RAbstractVector resultVector = (RAbstractVector) result;
             if (RType.Matrix.getName().equals(className)) {
@@ -138,7 +138,7 @@ public abstract class UpdateClass extends RBuiltinNode {
     @TruffleBoundary
     protected Object setClass(RAbstractContainer arg, RStringVector className) {
         controlVisibility();
-        RAbstractContainer result = arg.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) arg.getNonShared();
         return result.setClassAttr(className, false);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
index f60fdc88af1603b2378b62c9353df2c9191d6069..0431b88c2d7884d2095f7bf821e6398afff913c9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
@@ -25,10 +25,11 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RInvisibleBuiltinNode;
+import com.oracle.truffle.r.nodes.function.opt.ReuseNonSharedNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
-import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
 import com.oracle.truffle.r.runtime.RBuiltin;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -39,34 +40,27 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 @RBuiltin(name = "dim<-", kind = PRIMITIVE, parameterNames = {"x", "value"})
 public abstract class UpdateDim extends RInvisibleBuiltinNode {
 
-    @Child private CastIntegerNode castInteger;
-
-    private RAbstractIntVector castInteger(RAbstractVector vector) {
-        if (castInteger == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            castInteger = insert(CastIntegerNodeGen.create(true, false, false));
-        }
-        return (RAbstractIntVector) castInteger.execute(vector);
-    }
+    @Child private ReuseNonSharedNode reuse = ReuseNonSharedNode.create();
 
     @Specialization
     protected RAbstractVector updateDim(RAbstractVector vector, @SuppressWarnings("unused") RNull dimensions) {
         controlVisibility();
-        RVector result = (RVector) vector.materializeNonShared();
+        RVector result = ((RAbstractVector) reuse.execute(vector)).materialize();
         result.resetDimensions(null);
         return result;
     }
 
     @Specialization
-    protected RAbstractVector updateDim(RAbstractVector vector, RAbstractVector dimensions) {
+    protected RAbstractVector updateDim(RAbstractVector vector, RAbstractVector dimensions, //
+                    @Cached("createPreserveNames()") CastIntegerNode castInteger) {
         controlVisibility();
         if (dimensions.getLength() == 0) {
             CompilerDirectives.transferToInterpreter();
             throw RError.error(this, RError.Message.LENGTH_ZERO_DIM_INVALID);
         }
-        int[] dimsData = castInteger(dimensions).materialize().getDataCopy();
+        int[] dimsData = ((RAbstractIntVector) castInteger.execute(dimensions)).materialize().getDataCopy();
         RVector.verifyDimensions(vector.getLength(), dimsData, this);
-        RVector result = (RVector) vector.materializeNonShared();
+        RVector result = ((RAbstractVector) reuse.execute(vector)).materialize();
         result.resetDimensions(dimsData);
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index 56b3c8c2b86441d86a6e61607ef915af7b1d5ee8..5e604e8492d7d897056356d40f17e3cc68c0e643 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -94,7 +94,7 @@ public abstract class UpdateDimNames extends RInvisibleBuiltinNode {
     protected RAbstractContainer updateDimnamesNull(RAbstractContainer container, @SuppressWarnings("unused") RNull list, //
                     @Cached("create(DIMNAMES_ATTR_KEY)") RemoveAttributeNode remove) {
         controlVisibility();
-        RAbstractContainer result = container.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
         if (isRVectorProfile.profile(container instanceof RVector)) {
             RVector vector = (RVector) container;
             if (vector.getInternalDimNames() != null) {
@@ -117,7 +117,7 @@ public abstract class UpdateDimNames extends RInvisibleBuiltinNode {
     protected RAbstractContainer updateDimnames(RAbstractContainer container, RList list, //
                     @Cached("create(DIMNAMES_ATTR_KEY)") PutAttributeNode put) {
         controlVisibility();
-        RAbstractContainer result = container.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
         setDimNames(result, convertToListOfStrings(list), put);
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
index 0d3d387ae3876196022c19cb9b30c9986a3764fa..f1c8b0c90c229a39c25441613f00dfe9767fb050 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
@@ -43,7 +43,7 @@ public abstract class UpdateLevels extends RInvisibleBuiltinNode {
     @Specialization
     protected RAbstractVector updateLevels(RAbstractVector vector, @SuppressWarnings("unused") RNull levels) {
         controlVisibility();
-        RVector v = (RVector) vector.materializeNonShared();
+        RVector v = (RVector) vector.getNonShared();
         v.removeAttr(attrProfiles, RRuntime.LEVELS_ATTR_KEY);
         return v;
     }
@@ -51,7 +51,7 @@ public abstract class UpdateLevels extends RInvisibleBuiltinNode {
     @Specialization(guards = "levelsNotNull(levels)")
     protected RAbstractVector updateLevels(RAbstractVector vector, Object levels) {
         controlVisibility();
-        RVector v = (RVector) vector.materializeNonShared();
+        RVector v = (RVector) vector.getNonShared();
         v.setAttr(RRuntime.LEVELS_ATTR_KEY, castVector(levels));
         return v;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
index 1ff67547bc22a99ce42cc140f18880eab1726f90..4ff586756d9a60c91f905d0f030e3711cbb1b710 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
@@ -58,7 +58,7 @@ public abstract class UpdateNames extends RInvisibleBuiltinNode {
         controlVisibility();
         Object newNames = castString(names);
         if (newNames == RNull.instance) {
-            RAbstractContainer result = container.materializeNonShared();
+            RAbstractContainer result = (RAbstractContainer) container.getNonShared();
             result.setNames(null);
             return result;
         }
@@ -69,7 +69,7 @@ public abstract class UpdateNames extends RInvisibleBuiltinNode {
         } else {
             stringVector = (RStringVector) ((RAbstractVector) newNames).materialize();
         }
-        RAbstractContainer result = container.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
         if (stringVector.getLength() < result.getLength()) {
             stringVector = stringVector.copyResized(result.getLength(), true);
         } else if (stringVector == container) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
index 2e9e238247615b97e6a94296882e1f81d1c8777c..ced6ef86dc12a12de8c27ecae2555993f6dc9131 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
@@ -73,7 +73,7 @@ public abstract class UpdateOldClass extends RInvisibleBuiltinNode {
     @TruffleBoundary
     protected Object setOldClass(RAbstractContainer arg, RStringVector className) {
         controlVisibility();
-        RAbstractContainer result = arg.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) arg.getNonShared();
         return result.setClassAttr(className, false);
     }
 
@@ -81,7 +81,7 @@ public abstract class UpdateOldClass extends RInvisibleBuiltinNode {
     @TruffleBoundary
     protected Object setOldClass(RAbstractContainer arg, @SuppressWarnings("unused") RNull className) {
         controlVisibility();
-        RAbstractContainer result = arg.materializeNonShared();
+        RAbstractContainer result = (RAbstractContainer) arg.getNonShared();
         return result.setClassAttr(null, false);
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
index 739831680a32fb8089cc4e4e9f493683aa854445..a8ee35ebad0111baefdabfebe1200074f26f47a3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
@@ -52,7 +52,7 @@ public abstract class RRootNode extends RootNode implements HasSignature {
     private final FormalArguments formalArguments;
 
     protected RRootNode(SourceSection src, FormalArguments formalArguments, FrameDescriptor frameDescriptor) {
-        super(RContext.getEngine().getTruffleLanguage(), checkSourceSection(src), frameDescriptor);
+        super(RContext.getRForeignAccessFactory().getTruffleLanguage(), checkSourceSection(src), frameDescriptor);
         this.formalArguments = formalArguments;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index 0d5e62ae4781660c1cb44ef1abed4a4c7ac8521f..f6a101e149dab4e47ce4ee036603b8643db9eb9f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -64,8 +64,12 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+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.RAbstractRawVector;
+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.frame.FrameSlotChangeMonitor;
@@ -880,44 +884,43 @@ abstract class CheckTypeNode extends RBaseNode {
     private final RType type;
 
     CheckTypeNode(RType type) {
+        assert type != RType.Any;
         this.type = type;
     }
 
     @Specialization
-    boolean checkType(@SuppressWarnings("unused") Integer o) {
-        return type == RType.Any || type == RType.Integer || type == RType.Double ? true : false;
+    boolean checkType(@SuppressWarnings("unused") RAbstractIntVector o) {
+        return type == RType.Integer || type == RType.Double;
     }
 
     @Specialization
-    boolean checkType(@SuppressWarnings("unused") Double o) {
-        return type == RType.Any || type == RType.Integer || type == RType.Double ? true : false;
+    boolean checkType(@SuppressWarnings("unused") RAbstractDoubleVector o) {
+        return type == RType.Integer || type == RType.Double;
     }
 
     @Specialization
-    boolean checkType(@SuppressWarnings("unused") Byte o) {
-        return type == RType.Any || type == RType.Logical ? true : false;
+    boolean checkType(@SuppressWarnings("unused") RAbstractRawVector o) {
+        return type == RType.Logical;
     }
 
     @Specialization
-    boolean checkType(@SuppressWarnings("unused") String o) {
-        return type == RType.Any || type == RType.Character ? true : false;
+    boolean checkType(@SuppressWarnings("unused") RAbstractStringVector o) {
+        return type == RType.Character;
     }
 
     @Specialization
-    boolean checkType(@SuppressWarnings("unused") RStringVector o) {
-        return type == RType.Any || type == RType.Character ? true : false;
+    boolean checkType(@SuppressWarnings("unused") RAbstractComplexVector o) {
+        return type == RType.Complex;
     }
 
     @Specialization
     boolean checkType(@SuppressWarnings("unused") RFunction o) {
-        return type == RType.Any || type == RType.Function || type == RType.Closure || type == RType.Builtin || type == RType.Special ? true : false;
+        return type == RType.Function || type == RType.Closure || type == RType.Builtin || type == RType.Special;
     }
 
     @Fallback
     boolean checkType(Object o) {
-        if (type == RType.Any) {
-            return true;
-        } else if (type == RType.Function || type == RType.Closure || type == RType.Builtin || type == RType.Special) {
+        if (type == RType.Function || type == RType.Closure || type == RType.Builtin || type == RType.Special) {
             return o instanceof TruffleObject && !(o instanceof RTypedValue);
         } else {
             return false;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
index 70123f839c15e0b154621bf3daeafa56d7accca9..19c7b12cbb295cc31af46f47477e359350c09acd 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
@@ -52,7 +52,6 @@ import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory;
 /**
  * Represents a binary or unary operation from the 'logical' subset of Ops R group. The concrete
  * operation is implemented by factory object given as a constructor parameter, e.g.
- * {@link com.oracle.truffle.r.runtime.ops.BinaryCompare.Equal} or
  * {@link com.oracle.truffle.r.runtime.ops.BinaryLogic.And}.
  */
 public abstract class BinaryBooleanNode extends BinaryNodeBase {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
index a6b47df08fbe1e6680aceccc60eb82e8b5dbc14e..a9fbc9be4e7a714c57cf21e8d47bc528186c9075 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
@@ -28,10 +28,12 @@ import java.util.IdentityHashMap;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
+import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.access.FrameSlotNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
@@ -163,36 +165,51 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
         }
     }
 
-    @ExplodeLoop
-    public RArgsValuesAndNames evaluateFlatten(VirtualFrame frame, RArgsValuesAndNames varArgs) {
-        int size = arguments.length;
-        ArgumentsSignature resultSignature = null;
-        String[] names = null;
-        if (containsVarArgsSymbol()) {
-            size += (varArgs.getLength() - 1) * varArgsSymbolIndices.length;
-            names = new String[size];
-        } else {
-            resultSignature = signature;
+    private ArgumentsSignature cachedVarArgsSignature;
+    private ArgumentsSignature cachedResultSignature;
+    private final BranchProfile regenerateSignatureProfile = BranchProfile.create();
+
+    public ArgumentsSignature flattenNames(RArgsValuesAndNames varArgs) {
+        if (!containsVarArgsSymbol()) {
+            return signature;
         }
-        Object[] values = new Object[size];
+        ArgumentsSignature varArgsSignature = varArgs.getSignature();
+        if (cachedVarArgsSignature == null) {
+            CompilerDirectives.transferToInterpreter();
+        }
+        if (varArgsSignature == cachedVarArgsSignature) {
+            return cachedResultSignature;
+        }
+        regenerateSignatureProfile.enter();
+        cachedVarArgsSignature = varArgsSignature;
+        return cachedResultSignature = flattenNamesInternal(varArgsSignature);
+    }
+
+    @TruffleBoundary
+    private ArgumentsSignature flattenNamesInternal(ArgumentsSignature varArgs) {
+        String[] names = null;
+        int size = arguments.length + (varArgs.getLength() - 1) * varArgsSymbolIndices.length;
+        names = new String[size];
         int vargsSymbolsIndex = 0;
         int index = 0;
         for (int i = 0; i < arguments.length; i++) {
             if (vargsSymbolsIndex < varArgsSymbolIndices.length && varArgsSymbolIndices[vargsSymbolsIndex] == i) {
-                index = flattenVarArgs(frame, varArgs, names, values, index);
+                index = flattenVarArgNames(varArgs, names, index);
                 vargsSymbolsIndex++;
             } else {
-                values[index] = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame);
-                if (names != null) {
-                    names[index] = signature.getName(i);
-                }
-                index++;
+                names[index++] = signature.getName(i);
             }
         }
-        if (resultSignature == null) {
-            resultSignature = ArgumentsSignature.get(names);
+        return ArgumentsSignature.get(names);
+    }
+
+    private static int flattenVarArgNames(ArgumentsSignature varArgInfo, String[] names, int startIndex) {
+        int index = startIndex;
+        for (int j = 0; j < varArgInfo.getLength(); j++) {
+            names[index] = varArgInfo.getName(j);
+            index++;
         }
-        return new RArgsValuesAndNames(values, resultSignature);
+        return index;
     }
 
     @ExplodeLoop
@@ -216,7 +233,7 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
         return values;
     }
 
-    private int flattenVarArgs(VirtualFrame frame, RArgsValuesAndNames varArgInfo, String[] names, Object[] values, int startIndex) {
+    private int flattenVarArgsObject(VirtualFrame frame, RArgsValuesAndNames varArgInfo, Object[] values, int startIndex) {
         int index = startIndex;
         for (int j = 0; j < varArgInfo.getLength(); j++) {
             if (promiseHelper == null) {
@@ -224,7 +241,6 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
                 promiseHelper = insert(new PromiseCheckHelperNode());
             }
             values[index] = promiseHelper.checkEvaluate(frame, varArgInfo.getArgument(j));
-            names[index] = varArgInfo.getSignature().getName(j);
             index++;
         }
         return index;
@@ -265,17 +281,4 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
         }
         return result;
     }
-
-    private int flattenVarArgsObject(VirtualFrame frame, RArgsValuesAndNames varArgInfo, Object[] values, int startIndex) {
-        int index = startIndex;
-        for (int j = 0; j < varArgInfo.getLength(); j++) {
-            if (promiseHelper == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                promiseHelper = insert(new PromiseCheckHelperNode());
-            }
-            values[index] = promiseHelper.checkEvaluate(frame, varArgInfo.getArgument(j));
-            index++;
-        }
-        return index;
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 2f927add9f63457dbc41c674363a543a23317eca..3fd1262d5da9de9454e1510cf9bebcd44c0eb255 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -129,6 +129,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
      * Profiling for catching {@link ReturnException}s.
      */
     private final BranchProfile returnProfile = BranchProfile.create();
+    private final ConditionProfile returnTopLevelProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile returnHereProfile = ConditionProfile.createBinaryProfile();
 
     public static FunctionDefinitionNode create(SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, SaveArgumentsNode saveArguments, RSyntaxNode body,
@@ -262,7 +263,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         } catch (ReturnException ex) {
             returnProfile.enter();
             int depth = ex.getDepth();
-            if (returnHereProfile.profile(depth != -1 && RArguments.getDepth(frame) != depth)) {
+            if (returnTopLevelProfile.profile(depth != -1) && returnHereProfile.profile(RArguments.getDepth(frame) != depth)) {
                 throw ex;
             } else {
                 return ex.getResult();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
index e117aeaedcbcc941d2f6a5c5e2af6f7673d4fdfd..797b565714d8ae1a986c36dfd979d2cc305e499b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.PrimitiveValueProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.InlineCacheNode;
 import com.oracle.truffle.r.nodes.PromiseEvalFrameDebug;
@@ -138,6 +139,7 @@ public class PromiseHelperNode extends RBaseNode {
     private final ValueProfile multiVarArgsOptTypeProfile = ValueProfile.createIdentityProfile();
     private final ValueProfile promiseFrameProfile = ValueProfile.createClassProfile();
     private final BranchProfile varArgProfile = BranchProfile.create();
+    private final ConditionProfile chckPromiseMismatch = ConditionProfile.createBinaryProfile();
 
     /**
      * Guarded by {@link #isInOriginFrame(VirtualFrame,RPromise)}.
@@ -228,6 +230,8 @@ public class PromiseHelperNode extends RBaseNode {
         }
     }
 
+    private final PrimitiveValueProfile promiseEvalFrameLengthProfile = PrimitiveValueProfile.createEqualityProfile();
+
     /**
      * Checks to see if we need to create a {@link PromiseEvalFrame}. We cannot always just use
      * {@code promiseFrame} because it effectively resets the depth, so we wrap it, using the depth
@@ -236,13 +240,20 @@ public class PromiseHelperNode extends RBaseNode {
      * can occur so we don't need the {@link PromiseEvalFrame} (even if the frames are different).
      *
      */
-    private static Frame checkCreatePromiseEvalFrame(Frame frame, Frame promiseFrame, RPromise promise) {
-        if (frame != null && RArguments.getDepth(frame) != RArguments.getDepth(promiseFrame)) {
-            return PromiseEvalFrame.create(frame, promiseFrame.materialize(), promise);
+    private Frame checkCreatePromiseEvalFrame(Frame frame, Frame promiseFrame, RPromise promise) {
+        if (frame != null && chckPromiseMismatch.profile(RArguments.getDepth(frame) != RArguments.getDepth(promiseFrame))) {
+            return PromiseEvalFrame.create(frame, promiseFrame.materialize(), promise, promiseEvalFrameLengthProfile);
         } else {
             return promiseFrame;
         }
+    }
 
+    private static Frame checkCreatePromiseEvalFrameSlowPath(Frame frame, Frame promiseFrame, RPromise promise) {
+        if (frame != null && RArguments.getDepth(frame) != RArguments.getDepth(promiseFrame)) {
+            return PromiseEvalFrame.create(frame, promiseFrame.materialize(), promise, null);
+        } else {
+            return promiseFrame;
+        }
     }
 
     private Object generateValueEager(VirtualFrame frame, OptType optType, EagerPromise promise) {
@@ -313,7 +324,7 @@ public class PromiseHelperNode extends RBaseNode {
                 Frame promiseFrame = promise.getFrame();
                 assert promiseFrame != null;
                 try {
-                    Frame promiseEvalFrame = checkCreatePromiseEvalFrame(frame, promiseFrame, promise);
+                    Frame promiseEvalFrame = checkCreatePromiseEvalFrameSlowPath(frame, promiseFrame, promise);
                     if (PromiseEvalFrameDebug.enabled) {
                         PromiseEvalFrameDebug.doPromiseEval(true, frame, promiseFrame, promise);
                     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 7117b9d93ec754301f8f7e949ca6323419441b4a..06593f0cd3b723173cda71c2377d482b23d90489 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -68,7 +68,6 @@ import com.oracle.truffle.r.nodes.function.RCallNodeGen.FunctionDispatchNodeGen;
 import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.NoGenericMethodException;
 import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result;
 import com.oracle.truffle.r.nodes.function.call.PrepareArguments;
-import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.Arguments;
@@ -409,12 +408,12 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
                     @Cached("createPromiseHelper()") PromiseCheckHelperNode promiseHelperNode, //
                     @Cached("createUninitializedExplicitCall()") FunctionDispatch call) {
 
-        RArgsValuesAndNames argAndNames = explicitArgs != null ? (RArgsValuesAndNames) explicitArgs.execute(frame) : callArguments.evaluateFlatten(frame, lookupVarArgs(frame));
+        Object[] args = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getArguments() : callArguments.evaluateFlattenObjects(frame, lookupVarArgs(frame));
 
         RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin());
         RDispatch dispatch = builtin.getDispatch();
 
-        RStringVector typeX = classHierarchyNodeX.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(0)));
+        RStringVector typeX = classHierarchyNodeX.execute(promiseHelperNode.checkEvaluate(frame, args[0]));
         Result resultX = null;
         if (implicitTypeProfileX.profile(typeX != null)) {
             try {
@@ -424,8 +423,8 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
             }
         }
         Result resultY = null;
-        if (argAndNames.getLength() > 1 && dispatch == RDispatch.OPS_GROUP_GENERIC) {
-            RStringVector typeY = classHierarchyNodeY.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(1)));
+        if (args.length > 1 && dispatch == RDispatch.OPS_GROUP_GENERIC) {
+            RStringVector typeY = classHierarchyNodeY.execute(promiseHelperNode.checkEvaluate(frame, args[1]));
             if (implicitTypeProfileY.profile(typeY != null)) {
                 try {
                     resultY = dispatchLookupY.execute(frame, builtin.getName(), typeY, dispatch.getGroupGenericName(), frame.materialize(), null);
@@ -460,8 +459,8 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
                 }
             }
         }
-        S3Args s3Args;
-        RFunction resultFunction;
+        final S3Args s3Args;
+        final RFunction resultFunction;
         if (result == null) {
             s3Args = null;
             resultFunction = function;
@@ -473,7 +472,8 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
             }
             resultFunction = result.function;
         }
-        return call.execute(frame, resultFunction, argAndNames, s3Args);
+        ArgumentsSignature argsSignature = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getSignature() : callArguments.flattenNames(lookupVarArgs(frame));
+        return call.execute(frame, resultFunction, new RArgsValuesAndNames(args, argsSignature), s3Args);
     }
 
     protected class ForeignCall extends Node {
@@ -964,7 +964,6 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
     private static final class DispatchedCallNode extends LeafCallNode {
 
         @Child private DirectCallNode call;
-        @Child private RArgumentsNode argsNode;
         @Child private RFastPathNode fastPath;
 
         private final ArgumentsSignature signature;
@@ -989,17 +988,16 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
                 fastPath = null;
             }
 
-            if (argsNode == null) {
+            if (call == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                argsNode = insert(RArgumentsNode.create());
                 call = insert(Truffle.getRuntime().createDirectCallNode(cachedFunction.getTarget()));
                 if (needsSplitting(cachedFunction)) {
                     call.cloneCallTarget();
                 }
             }
-            MaterializedFrame callerFrame = CompilerDirectives.inInterpreter() || originalCall.needsCallerFrame ? frame.materialize() : null;
-            Object[] argsObject = argsNode.execute(cachedFunction, originalCall.createCaller(frame, cachedFunction), callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame),
-                            orderedArguments, signature, s3Args);
+            MaterializedFrame callerFrame = /* CompilerDirectives.inInterpreter() || */originalCall.needsCallerFrame ? frame.materialize() : null;
+            Object[] argsObject = RArguments.create(cachedFunction, originalCall.createCaller(frame, cachedFunction), callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame),
+                            orderedArguments, signature, cachedFunction.getEnclosingFrame(), s3Args);
             return call.call(frame, argsObject);
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java
index 9de276c9d04a3b1133b0e61060d795002058e336..721826a0a6a8c6e36ef3a5b5a0f19530873f0698 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.access.FrameSlotNode;
 import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
@@ -51,6 +52,7 @@ public abstract class OptVariablePromiseBaseNode extends PromiseNode implements
     private final int wrapIndex;
 
     private final ConditionProfile promiseEvalFrameProfile = ConditionProfile.createBinaryProfile();
+    private final ValueProfile frameProfile = ValueProfile.createClassProfile();
 
     public OptVariablePromiseBaseNode(RPromiseFactory factory, ReadVariableNode rvn, int wrapIndex) {
         super(factory);
@@ -71,7 +73,7 @@ public abstract class OptVariablePromiseBaseNode extends PromiseNode implements
     public Object execute(VirtualFrame initialFrame) {
         VirtualFrame frame;
         if (promiseEvalFrameProfile.profile(initialFrame instanceof PromiseEvalFrame)) {
-            frame = SubstituteVirtualFrame.create(((PromiseEvalFrame) initialFrame).getOriginalFrame());
+            frame = frameProfile.profile(SubstituteVirtualFrame.create(((PromiseEvalFrame) initialFrame).getOriginalFrame()));
         } else {
             frame = initialFrame;
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..70aa1febcc3f89bd62a47e8a2adedf89b42c399a
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016, 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.function.opt;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.runtime.data.RShareable;
+import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
+
+public abstract class ReuseNonSharedNode extends Node {
+
+    public static ReuseNonSharedNode create() {
+        return ReuseNonSharedNodeGen.create();
+    }
+
+    public abstract Object execute(Object value);
+
+    @Specialization
+    protected RShareable getStorage(RSharingAttributeStorage value, //
+                    @Cached("createBinaryProfile()") ConditionProfile isSharedProfile, //
+                    @Cached("createBinaryProfile()") ConditionProfile isTemporaryProfile, //
+                    @Cached("createClassProfile()") ValueProfile copyProfile) {
+        if (isSharedProfile.profile(value.isShared())) {
+            RShareable res = copyProfile.profile(value).copy();
+            assert res.isTemporary();
+            res.incRefCount();
+            return res;
+        }
+        if (isTemporaryProfile.profile(value.isTemporary())) {
+            value.incRefCount();
+        }
+        return value;
+    }
+
+    @Specialization(contains = "getStorage")
+    protected static RShareable getRShareable(RShareable value, //
+                    @Cached("createBinaryProfile()") ConditionProfile isSharedProfile, //
+                    @Cached("createBinaryProfile()") ConditionProfile isTemporaryProfile) {
+        if (isSharedProfile.profile(value.isShared())) {
+            RShareable res = value.copy();
+            assert res.isTemporary();
+            res.incRefCount();
+            return res;
+        }
+        if (isTemporaryProfile.profile(value.isTemporary())) {
+            value.incRefCount();
+        }
+        return value;
+    }
+
+    protected static boolean isRShareable(Object value) {
+        return value instanceof RShareable;
+    }
+
+    @Specialization(guards = "!isRShareable(value)")
+    protected static Object getNonShareable(Object value) {
+        return value;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java
index b05d17ea20f260ae2c35def3d0212bf3bb216958..3573d38864dd81f79000f0226f7e2f13c7de6fc6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 
 /**
  * Contains helper nodes related to factors, special R class of {@link RAbstractIntVector}. Note:
- * there is also {@see IsFactorNode}, which implements a built-in, for checking factor class.
+ * there is also {@code IsFactorNode}, which implements a built-in, for checking factor class.
  */
 public final class RFactorNodes {
 
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 7b15cf7fede1479f5f3718de78a5bbf3983a8978..617d540e4023f0f517cc36627f4d69d645515f8f 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
@@ -224,4 +224,8 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
     public static CastIntegerNode createNonPreserving() {
         return CastIntegerNodeGen.create(false, false, false);
     }
+
+    public static CastIntegerNode createPreserveNames() {
+        return CastIntegerNodeGen.create(false, false, false);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
index 6c0435a2331e44dd7ed1930a6bbbeb34af9ce1bf..4166d6769e61f47b19a8fcf908cf34e27d2392e3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RSerialize;
 import com.oracle.truffle.r.runtime.data.RShareable;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -41,7 +42,7 @@ public abstract class GetNonSharedNode extends RNode implements RSyntaxNode {
     private final ValueProfile shareableTypeProfile = ValueProfile.createClassProfile();
 
     @Specialization
-    protected RShareable getNonShared(RShareable shareable) {
+    protected RTypedValue getNonShared(RShareable shareable) {
         return shareableTypeProfile.profile(shareable).getNonShared();
     }
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
index 72defec846a50ae449017d572d95353bb1494f9c..a3fce16a371db2d0b0cd9e14e07377b988827154 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
@@ -54,9 +54,11 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RS4Object;
+import com.oracle.truffle.r.runtime.data.RScalar;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
@@ -538,6 +540,15 @@ public class CallRFFIHelper {
         }
     }
 
+    public static int OBJECT(Object x) {
+        if (x instanceof RTypedValue && !(x instanceof RScalar)) {
+            return ((RTypedValue) x).getIsObject();
+        } else {
+            // TODO: should we throw an error or simply return false for scalars
+            throw RInternalError.unimplemented();
+        }
+    }
+
     public static Object Rf_duplicate(Object x) {
         guaranteeInstanceOf(x, RAbstractVector.class);
         return ((RAbstractVector) x).copy();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/AbstractVirtualEvalFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/AbstractVirtualEvalFrame.java
index 136dc08e927b09feb829794000b7cca179ff7f1a..7cd24cbbc97cf3bfe0d0c7e2452d4ed2851a779b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/AbstractVirtualEvalFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/AbstractVirtualEvalFrame.java
@@ -22,15 +22,12 @@
  */
 package com.oracle.truffle.r.runtime;
 
-import java.util.Arrays;
-
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.runtime.data.RFunction;
 
 /**
  * Supports {@link VirtualEvalFrame} and {@link PromiseEvalFrame}.
@@ -40,13 +37,9 @@ public abstract class AbstractVirtualEvalFrame implements VirtualFrame, Material
     protected final MaterializedFrame originalFrame;
     @CompilationFinal protected final Object[] arguments;
 
-    protected AbstractVirtualEvalFrame(MaterializedFrame originalFrame, RFunction function, RCaller call, int depth) {
+    protected AbstractVirtualEvalFrame(MaterializedFrame originalFrame, Object[] arguments) {
         this.originalFrame = originalFrame;
-        this.arguments = Arrays.copyOf(originalFrame.getArguments(), originalFrame.getArguments().length);
-        this.arguments[RArguments.INDEX_DEPTH] = depth;
-        this.arguments[RArguments.INDEX_IS_IRREGULAR] = true;
-        this.arguments[RArguments.INDEX_FUNCTION] = function;
-        this.arguments[RArguments.INDEX_CALL] = call;
+        this.arguments = arguments;
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PromiseEvalFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PromiseEvalFrame.java
index c96666c89a9c9c9efcf05a5d5608b8a72ddfffbb..c131416d1307600cf8d91b9be61d77737e253727 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PromiseEvalFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PromiseEvalFrame.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime;
 
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.profiles.PrimitiveValueProfile;
 import com.oracle.truffle.r.runtime.data.RPromise;
 
 /**
@@ -56,13 +57,19 @@ public final class PromiseEvalFrame extends AbstractVirtualEvalFrame {
      */
     private final RPromise promise;
 
-    private PromiseEvalFrame(Frame topFrame, MaterializedFrame originalFrame, RPromise promise) {
-        super(originalFrame, RArguments.getFunction(originalFrame), RArguments.getCall(originalFrame), RArguments.getDepth(topFrame));
+    private PromiseEvalFrame(MaterializedFrame originalFrame, Object[] arguments, RPromise promise) {
+        super(originalFrame, arguments);
         this.promise = promise;
     }
 
-    public static PromiseEvalFrame create(Frame topFrame, MaterializedFrame promiseFrame, RPromise promise) {
-        PromiseEvalFrame result = new PromiseEvalFrame(topFrame, promiseFrame instanceof PromiseEvalFrame ? ((PromiseEvalFrame) promiseFrame).getOriginalFrame() : promiseFrame, promise);
+    public static PromiseEvalFrame create(Frame topFrame, MaterializedFrame promiseFrame, RPromise promise, PrimitiveValueProfile lengthProfile) {
+        MaterializedFrame originalFrame = promiseFrame instanceof PromiseEvalFrame ? ((PromiseEvalFrame) promiseFrame).getOriginalFrame() : promiseFrame;
+        int length = lengthProfile == null ? originalFrame.getArguments().length : lengthProfile.profile(originalFrame.getArguments().length);
+        Object[] arguments = new Object[length];
+        System.arraycopy(originalFrame.getArguments(), 0, arguments, 0, length);
+        arguments[RArguments.INDEX_DEPTH] = RArguments.getDepth(topFrame);
+        arguments[RArguments.INDEX_IS_IRREGULAR] = true;
+        PromiseEvalFrame result = new PromiseEvalFrame(originalFrame, arguments, promise);
         result.arguments[RArguments.INDEX_PROMISE_FRAME] = result;
         return result;
     }
@@ -74,5 +81,4 @@ public final class PromiseEvalFrame extends AbstractVirtualEvalFrame {
     public RPromise getPromise() {
         return promise;
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
index a45378ddf386a42d0d0b7b6b21a4e2a5de927450..e8ea46f80d38dd1ee8b90445017530ade08304a8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
@@ -368,6 +368,7 @@ public class RSerialize {
 
         protected Object readItem(int flags) throws IOException {
             int levs = flags >>> 12;
+            int isObj = (flags & Flags.IS_OBJECT_BIT_MASK) == 0 ? 0 : 1;
             Object result = null;
             SEXPTYPE type = SEXPTYPE.mapInt(Flags.ptype(flags));
 
@@ -604,6 +605,7 @@ public class RSerialize {
 
                     if (!(result instanceof RScalar)) {
                         ((RTypedValue) result).setGPBits(levs);
+                        ((RTypedValue) result).setIsObject(isObj);
                     } else {
                         // for now we only record S4-ness here, and in this case it shoud be 0
                         assert (levs == 0);
@@ -774,7 +776,6 @@ public class RSerialize {
                 default:
                     throw RInternalError.unimplemented();
             }
-            // TODO SETLEVELS
             if (type == SEXPTYPE.CHARSXP) {
                 /*
                  * With the CHARSXP cache maintained through the ATTRIB field that field has already
@@ -786,6 +787,10 @@ public class RSerialize {
                     readItem();
                 }
             } else {
+                // TODO: CHARSXP currently cannot be an object - this is not the case in GNU R
+                if (!(result instanceof RScalar)) {
+                    ((RTypedValue) result).setIsObject(isObj);
+                }
                 if (Flags.hasAttr(flags)) {
                     Object attr = readItem();
                     result = setAttributes(result, attr);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/VirtualEvalFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/VirtualEvalFrame.java
index 0f7206226a7c9d62589b379ef75feebbe8fd2519..196f37799ec925339d47be8dff41987501b1cf30 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/VirtualEvalFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/VirtualEvalFrame.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.runtime;
 
+import java.util.Arrays;
+
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -31,12 +33,16 @@ import com.oracle.truffle.r.runtime.data.RFunction;
  */
 public final class VirtualEvalFrame extends AbstractVirtualEvalFrame {
 
-    private VirtualEvalFrame(MaterializedFrame originalFrame, RFunction function, RCaller call, int depth) {
-        super(originalFrame, function, call, depth);
+    private VirtualEvalFrame(MaterializedFrame originalFrame, Object[] arguments) {
+        super(originalFrame, arguments);
     }
 
     public static VirtualEvalFrame create(MaterializedFrame originalFrame, RFunction function, RCaller call, int depth) {
-        return new VirtualEvalFrame(originalFrame, function, call, depth);
+        Object[] arguments = Arrays.copyOf(originalFrame.getArguments(), originalFrame.getArguments().length);
+        arguments[RArguments.INDEX_DEPTH] = depth;
+        arguments[RArguments.INDEX_IS_IRREGULAR] = true;
+        arguments[RArguments.INDEX_FUNCTION] = function;
+        arguments[RArguments.INDEX_CALL] = call;
+        return new VirtualEvalFrame(originalFrame, arguments);
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 770f37352da5afd6dc6ee1d7248b2566f5962274..58a135e705e73f61cd5b64a1d618a6887615c5dd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -346,7 +346,7 @@ public class ConnectionSupport {
 
     // TODO implement all open modes
 
-    public static class InvalidConnection extends RConnection {
+    public static final class InvalidConnection extends RConnection {
 
         public static final InvalidConnection instance = new InvalidConnection();
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 62dfc593511b0f906534477dc6fa8c6a19bc8067..10f69829220c49fb43baa959cdc872f909715487 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -370,7 +370,7 @@ public abstract class RConnection extends RAttributeStorage implements RTypedVal
     }
 
     @Override
-    public RAbstractContainer materializeNonShared() {
+    public RTypedValue getNonShared() {
         return this;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
index 20c50d3593de1bcdd699c3f4a24b53a064c937c6..f70ade38916c468075d4431db4c0672ea5bc86af 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
@@ -27,9 +27,7 @@ import java.io.IOException;
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RError;
@@ -38,7 +36,6 @@ import com.oracle.truffle.r.runtime.RSerialize;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
@@ -201,9 +198,4 @@ public interface Engine {
     String toString(Object value);
 
     RFunction parseFunction(String name, Source source, MaterializedFrame enclosingFrame) throws ParseException;
-
-    ForeignAccess getForeignAccess(RTypedValue value);
-
-    Class<? extends TruffleLanguage<RContext>> getTruffleLanguage();
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 050000c91fc663d5ae2a5bebe4b13f68a69febc2..d0a10d3b4a3ad10f25aaf107641db694a9006a23 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.context;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
@@ -302,6 +303,7 @@ public final class RContext extends ExecutionContext implements TruffleObject {
     @CompilationFinal private static RCodeBuilder<RSyntaxNode> astBuilder;
     @CompilationFinal private static RRuntimeASTAccess runtimeASTAccess;
     @CompilationFinal private static RBuiltinLookup builtinLookup;
+    @CompilationFinal private static RForeignAccessFactory foreignAccessFactory;
     @CompilationFinal private static boolean initialContextInitialized;
 
     public static boolean isInitialContextInitialized() {
@@ -311,10 +313,11 @@ public final class RContext extends ExecutionContext implements TruffleObject {
     /**
      * Initialize VM-wide static values.
      */
-    public static void initialize(RCodeBuilder<RSyntaxNode> rAstBuilder, RRuntimeASTAccess rRuntimeASTAccess, RBuiltinLookup rBuiltinLookup) {
+    public static void initialize(RCodeBuilder<RSyntaxNode> rAstBuilder, RRuntimeASTAccess rRuntimeASTAccess, RBuiltinLookup rBuiltinLookup, RForeignAccessFactory rForeignAccessFactory) {
         RContext.astBuilder = rAstBuilder;
         RContext.runtimeASTAccess = rRuntimeASTAccess;
         RContext.builtinLookup = rBuiltinLookup;
+        RContext.foreignAccessFactory = rForeignAccessFactory;
     }
 
     /**
@@ -620,6 +623,10 @@ public final class RContext extends ExecutionContext implements TruffleObject {
         return builtinLookup.lookupBuiltinDescriptor(name);
     }
 
+    public static RForeignAccessFactory getRForeignAccessFactory() {
+        return foreignAccessFactory;
+    }
+
     public RCmdOptions getOptions() {
         return info.getOptions();
     }
@@ -667,4 +674,15 @@ public final class RContext extends ExecutionContext implements TruffleObject {
     public ForeignAccess getForeignAccess() {
         throw new IllegalStateException("cannot access " + RContext.class.getSimpleName() + " via Truffle");
     }
+
+    public static Closeable withinContext(RContext context) {
+        RContext oldContext = RContext.threadLocalContext.get();
+        RContext.threadLocalContext.set(context);
+        return new Closeable() {
+            @Override
+            public void close() {
+                RContext.threadLocalContext.set(oldContext);
+            }
+        };
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RGPBits.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java
similarity index 65%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RGPBits.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java
index 88f02cb4a5c9014eb60acc80adb054f898381c60..54b789c5cc6a4d57fa58dc25df3cf12699b1374a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RGPBits.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2016, 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
@@ -20,17 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.data;
+package com.oracle.truffle.r.runtime.context;
 
-/**
- * This corresponds to the "general purpose" bits in a GnuR SEXP. It is now rarely used within GnuR
- * and many of those uses do not apply to FastR; however, condition handling is one important use.
- * We define it as an interface so that only specific types need implement it, {@link RList} in the
- * case of condition handling.
- *
- */
-public interface RGPBits {
-    int getGPBits();
+import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
+
+public interface RForeignAccessFactory {
+
+    ForeignAccess getForeignAccess(RTypedValue value);
 
-    void setGPBits(int value);
+    Class<? extends TruffleLanguage<RContext>> getTruffleLanguage();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBaseObject.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBaseObject.java
index 7d28b31916c625660275257f563f621cd9dbe895..d292a67ba3d34572f0fb3ff69aed312c674de3f4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBaseObject.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBaseObject.java
@@ -24,13 +24,13 @@ package com.oracle.truffle.r.runtime.data;
 
 abstract class RBaseObject {
 
-    protected int gpbits;
+    protected int typedValueInfo;
 
-    public int getGPBits() {
-        return gpbits;
+    public int getTypedValueInfo() {
+        return typedValueInfo;
     }
 
-    public void setGPBits(int value) {
-        gpbits = value;
+    public void setTypedValueInfo(int value) {
+        typedValueInfo = value;
     }
 }
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 a365680d20d128c48ab93657ad3970982033a771..89c4e120abebe455a132f52cf4763afe54425e80 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
@@ -115,12 +115,6 @@ public class RExpression implements RShareable, RAbstractContainer {
         return RExpression.class;
     }
 
-    @Override
-    public RExpression materializeNonShared() {
-        RVector d = data.materializeNonShared();
-        return data != d ? RDataFactory.createExpression((RList) d) : this;
-    }
-
     @Override
     public Object getDataAtAsObject(int index) {
         return data.getDataAtAsObject(index);
@@ -233,12 +227,12 @@ public class RExpression implements RShareable, RAbstractContainer {
     }
 
     @Override
-    public int getGPBits() {
-        return data.getGPBits();
+    public int getTypedValueInfo() {
+        return data.getTypedValueInfo();
     }
 
     @Override
-    public void setGPBits(int value) {
-        data.setGPBits(value);
+    public void setTypedValueInfo(int value) {
+        data.setTypedValueInfo(value);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
index c377084e34bb23d370ff602e1c4a7d319ae47d8f..db973989b0788abce48a22f4d2fe3e1c96d87652 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
@@ -119,7 +119,7 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV
 
     @Override
     public ForeignAccess getForeignAccess() {
-        return RContext.getEngine().getForeignAccess(this);
+        return RContext.getRForeignAccessFactory().getForeignAccess(this);
     }
 
     public FastPathFactory getFastPath() {
@@ -144,7 +144,7 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV
             }
             newFunction.initAttributes(newAttributes);
         }
-        newFunction.gpbits = gpbits;
+        newFunction.typedValueInfo = typedValueInfo;
         return newFunction;
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index a053031e4e044207e4ceed3c5c538314a280e247..569771fa7b047549bed0e0c6a7e10beb3acd3532 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -127,11 +127,6 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
         return RLanguage.class;
     }
 
-    @Override
-    public RLanguage materializeNonShared() {
-        return (RLanguage) getNonShared();
-    }
-
     @Override
     public RShareable materializeToShareable() {
         // TODO is copy necessary?
@@ -198,7 +193,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
         if (this.attributes != null) {
             l.attributes = attributes.copy();
         }
-        l.gpbits = gpbits;
+        l.typedValueInfo = typedValueInfo;
         return l;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
index b4b18d7de41321683bcec333e2a853a379beb582..e93178a5db5e3d67f69f1a46f1a55878b1482615 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.context.RContext;
 
-public final class RList extends RListBase implements RGPBits, TruffleObject {
+public final class RList extends RListBase implements TruffleObject {
 
     private static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.List.getClazz());
 
@@ -86,6 +86,6 @@ public final class RList extends RListBase implements RGPBits, TruffleObject {
 
     @Override
     public ForeignAccess getForeignAccess() {
-        return RContext.getEngine().getForeignAccess(this);
+        return RContext.getRForeignAccessFactory().getForeignAccess(this);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index b265557d72aa6a0bfbbd8ece789dfde9b2267332..bc3fe353635825c7ea4c1a29f1243ce8e3efc234 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -236,7 +236,7 @@ public class RPairList extends RAttributeStorage implements RAbstractContainer {
     }
 
     @Override
-    public RVector materializeNonShared() {
+    public RVector getNonShared() {
         RInternalError.shouldNotReachHere();
         return null;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
index e956c0faec14e3357cfe3b4e692b7e480a48ac40..dce983013195da94e1266aa8495c123baa96a6aa 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
@@ -487,12 +487,12 @@ public class RPromise implements RTypedValue {
     }
 
     @Override
-    public int getGPBits() {
+    public int getTypedValueInfo() {
         return 0;
     }
 
     @Override
-    public void setGPBits(int value) {
+    public void setTypedValueInfo(int value) {
         // This gets called from RSerialize, just ignore (for now)
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java
index 017c036641292185cbf88247444e60e0a2c8a68b..4c2c87f3561321c799c0777fb6164f478371988b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java
@@ -56,7 +56,7 @@ public class RS4Object extends RSharingAttributeStorage {
                 newAttributes.put(attr.getName(), attr.getValue());
             }
         }
-        resultS4.gpbits = gpbits;
+        resultS4.typedValueInfo = typedValueInfo;
         return resultS4;
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalar.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalar.java
index 402b8b2d417d00093f0a41b709fb69b97f300065..332ab5cf0270a00698282e6decd09e3889a79cfb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalar.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalar.java
@@ -29,12 +29,12 @@ import com.oracle.truffle.r.runtime.RInternalError;
 public abstract class RScalar implements RTypedValue {
 
     @Override
-    public int getGPBits() {
+    public int getTypedValueInfo() {
         throw RInternalError.shouldNotReachHere();
     }
 
     @Override
-    public void setGPBits(int value) {
+    public void setTypedValueInfo(int value) {
         throw RInternalError.shouldNotReachHere();
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
index e494a76e15735df71912cfae0f58a732814e44fc..6d7ddced925c96d8bebedfbb4b98892d18dba52f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
@@ -81,8 +81,8 @@ public abstract class RScalarVector extends RScalar implements RAbstractVector {
     }
 
     @Override
-    public RAbstractContainer materializeNonShared() {
-        return materialize().materializeNonShared();
+    public RTypedValue getNonShared() {
+        return materialize().getNonShared();
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
index bac78060ac764a9f604c3357e0031fedff2729f5..df3204230ada99193b5ba8a0003154bd26105c0f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
@@ -169,9 +169,8 @@ public abstract class RSequence implements RAbstractVector {
     }
 
     @Override
-    public final RVector materializeNonShared() {
-        RVector resultVector = this.materialize().materializeNonShared();
-        return resultVector;
+    public final RTypedValue getNonShared() {
+        return materialize().getNonShared();
     }
 
     @Override
@@ -189,12 +188,12 @@ public abstract class RSequence implements RAbstractVector {
     }
 
     @Override
-    public int getGPBits() {
+    public int getTypedValueInfo() {
         return 0;
     }
 
     @Override
-    public void setGPBits(int value) {
+    public void setTypedValueInfo(int value) {
         throw RInternalError.shouldNotReachHere();
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RShareable.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RShareable.java
index 029e4443be0f1e1e5279f0d9cbfc1d31b3fd56ae..2e008ca8f5facebe3c0641fde1cd26170035eaf0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RShareable.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RShareable.java
@@ -22,7 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
-public interface RShareable {
+public interface RShareable extends RTypedValue {
 
     // SHARED_PERMANENT_VAL describes both overflow value and a value that can be set to prevent
     // further updates to ref count (for sharing between different threads) - can potentially be
@@ -48,6 +48,6 @@ public interface RShareable {
 
     void makeSharedPermanent();
 
-    RShareable getNonShared();
+    RTypedValue getNonShared();
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
index a915cdb26f7d7fbd646c660a55c3491af963bc73..f87a82b76a8197add0a2772ee67f94b133ae5dd0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
@@ -61,7 +61,7 @@ public abstract class RSharingAttributeStorage extends RAttributeStorage impleme
     }
 
     @Override
-    public RShareable getNonShared() {
+    public RTypedValue getNonShared() {
         if (isShared()) {
             RShareable res = copy();
             assert res.isTemporary();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
index 91aa4dac85d953b1f097f8b7360d9c5a44dea08e..234a6878594186acf6d35192747b1cf2747e9360 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
@@ -22,13 +22,34 @@ import com.oracle.truffle.r.runtime.RType;
 public interface RTypedValue {
 
     // mask values are the same as in GNU R
+    // as is the layout of data (but it's never exposed so it does not matter for correctness)
     int S4_MASK = 1 << 4;
+    int IS_OBJECT_MASK_SHIFT = 5;
+    int IS_OBJECT_BITS_MASK = 1 << IS_OBJECT_MASK_SHIFT;
+    int GP_BITS_MASK_SHIFT = 8;
+    int GP_BITS_MASK = 0xFFFF << GP_BITS_MASK_SHIFT;
 
     RType getRType();
 
-    int getGPBits();
+    int getTypedValueInfo();
 
-    void setGPBits(int value);
+    void setTypedValueInfo(int value);
+
+    default int getIsObject() {
+        return (getTypedValueInfo() & IS_OBJECT_BITS_MASK) >>> IS_OBJECT_MASK_SHIFT;
+    }
+
+    default void setIsObject(int gpbits) {
+        setTypedValueInfo((getTypedValueInfo() & ~IS_OBJECT_BITS_MASK) | (gpbits << IS_OBJECT_MASK_SHIFT));
+    }
+
+    default int getGPBits() {
+        return (getTypedValueInfo() & GP_BITS_MASK) >>> GP_BITS_MASK_SHIFT;
+    }
+
+    default void setGPBits(int gpbits) {
+        setTypedValueInfo((getTypedValueInfo() & ~GP_BITS_MASK) | (gpbits << GP_BITS_MASK_SHIFT));
+    }
 
     default boolean isS4() {
         return (getGPBits() & S4_MASK) == S4_MASK;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index 9292adf55f7794dcdcb8e2696eff364b578e5890..2bfc99228b289084e8d688cfeaad8385bcf9ad3a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -554,7 +554,7 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare
         RVector result = internalCopy();
         setAttributes(result);
         incCopyCount();
-        result.gpbits = gpbits;
+        result.typedValueInfo = typedValueInfo;
         return result;
     }
 
@@ -788,11 +788,6 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare
         return implicitClassHeader;
     }
 
-    @Override
-    public RVector materializeNonShared() {
-        return (RVector) getNonShared();
-    }
-
     @Override
     public final RShareable materializeToShareable() {
         return materialize();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
index 21952499cc71457ff6317756bc8985a0387ee086..a0a74fcdcb3df189eb2397dee4f99d42ed18306d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.r.runtime.data.RAttributes;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RShareable;
 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;
@@ -174,8 +175,8 @@ abstract class RToVectorClosure implements RAbstractVector {
     }
 
     @Override
-    public final RAbstractVector materializeNonShared() {
-        return (RAbstractVector) vector.materializeNonShared();
+    public final RTypedValue getNonShared() {
+        return vector.getNonShared();
     }
 
     @Override
@@ -184,13 +185,13 @@ abstract class RToVectorClosure implements RAbstractVector {
     }
 
     @Override
-    public int getGPBits() {
-        return vector.getGPBits();
+    public int getTypedValueInfo() {
+        return vector.getTypedValueInfo();
     }
 
     @Override
-    public void setGPBits(int value) {
-        vector.setGPBits(value);
+    public void setTypedValueInfo(int value) {
+        vector.setTypedValueInfo(value);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
index ebe23dd5ce124f744a817b151e4f6ff32c85dbef..befd4e867877b9b1375e1184dec6ca9686960c2e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
@@ -45,7 +45,7 @@ public interface RAbstractContainer extends RAttributable, RTypedValue {
 
     Class<?> getElementClass();
 
-    RAbstractContainer materializeNonShared();
+    RTypedValue getNonShared();
 
     RShareable materializeToShareable();
 
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 18f116db02c61461015861d4cd831859be250f68..a868f5a1870f21b0536d57e409040b27c8c4f382 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
@@ -82,6 +82,6 @@ public interface RAbstractVector extends RAbstractContainer, TruffleObject {
 
     @Override
     default ForeignAccess getForeignAccess() {
-        return RContext.getEngine().getForeignAccess(this);
+        return RContext.getRForeignAccessFactory().getForeignAccess(this);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
index 69da8f799bce1ea6f825880c4359a1292fceeb39..af7d7af6ec7e74c8c527523e9c58216cd6736c29 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.RArguments;
 
 /**
@@ -38,6 +39,8 @@ import com.oracle.truffle.r.runtime.RArguments;
  */
 public final class NSBaseMaterializedFrame implements MaterializedFrame {
 
+    private static final ValueProfile frameProfile = ValueProfile.createClassProfile();
+
     private final MaterializedFrame packageBaseFrame;
     @CompilationFinal private final Object[] arguments;
 
@@ -52,6 +55,10 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame {
         RArguments.initializeEnclosingFrame(this, globalFrame);
     }
 
+    private MaterializedFrame getPackageBaseFrame() {
+        return frameProfile.profile(packageBaseFrame);
+    }
+
     public void updateGlobalFrame(MaterializedFrame globalFrame) {
         RArguments.setEnclosingFrame(this, globalFrame);
     }
@@ -62,7 +69,7 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame {
 
     @Override
     public FrameDescriptor getFrameDescriptor() {
-        return packageBaseFrame.getFrameDescriptor();
+        return getPackageBaseFrame().getFrameDescriptor();
     }
 
     @Override
@@ -81,111 +88,111 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame {
 
     @Override
     public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getObject(slot);
+        return getPackageBaseFrame().getObject(slot);
     }
 
     @Override
     public void setObject(FrameSlot slot, Object value) {
-        packageBaseFrame.setObject(slot, value);
+        getPackageBaseFrame().setObject(slot, value);
     }
 
     @Override
     public byte getByte(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getByte(slot);
+        return getPackageBaseFrame().getByte(slot);
     }
 
     @Override
     public void setByte(FrameSlot slot, byte value) {
-        packageBaseFrame.setByte(slot, value);
+        getPackageBaseFrame().setByte(slot, value);
     }
 
     @Override
     public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getBoolean(slot);
+        return getPackageBaseFrame().getBoolean(slot);
     }
 
     @Override
     public void setBoolean(FrameSlot slot, boolean value) {
-        packageBaseFrame.setBoolean(slot, value);
+        getPackageBaseFrame().setBoolean(slot, value);
     }
 
     @Override
     public int getInt(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getInt(slot);
+        return getPackageBaseFrame().getInt(slot);
     }
 
     @Override
     public void setInt(FrameSlot slot, int value) {
-        packageBaseFrame.setInt(slot, value);
+        getPackageBaseFrame().setInt(slot, value);
     }
 
     @Override
     public long getLong(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getLong(slot);
+        return getPackageBaseFrame().getLong(slot);
     }
 
     @Override
     public void setLong(FrameSlot slot, long value) {
-        packageBaseFrame.setLong(slot, value);
+        getPackageBaseFrame().setLong(slot, value);
     }
 
     @Override
     public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getFloat(slot);
+        return getPackageBaseFrame().getFloat(slot);
     }
 
     @Override
     public void setFloat(FrameSlot slot, float value) {
-        packageBaseFrame.setFloat(slot, value);
+        getPackageBaseFrame().setFloat(slot, value);
     }
 
     @Override
     public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getDouble(slot);
+        return getPackageBaseFrame().getDouble(slot);
     }
 
     @Override
     public void setDouble(FrameSlot slot, double value) {
-        packageBaseFrame.setDouble(slot, value);
+        getPackageBaseFrame().setDouble(slot, value);
     }
 
     @Override
     public Object getValue(FrameSlot slot) {
-        return packageBaseFrame.getValue(slot);
+        return getPackageBaseFrame().getValue(slot);
     }
 
     @Override
     public boolean isObject(FrameSlot slot) {
-        return packageBaseFrame.isObject(slot);
+        return getPackageBaseFrame().isObject(slot);
     }
 
     @Override
     public boolean isByte(FrameSlot slot) {
-        return packageBaseFrame.isByte(slot);
+        return getPackageBaseFrame().isByte(slot);
     }
 
     @Override
     public boolean isBoolean(FrameSlot slot) {
-        return packageBaseFrame.isBoolean(slot);
+        return getPackageBaseFrame().isBoolean(slot);
     }
 
     @Override
     public boolean isInt(FrameSlot slot) {
-        return packageBaseFrame.isInt(slot);
+        return getPackageBaseFrame().isInt(slot);
     }
 
     @Override
     public boolean isLong(FrameSlot slot) {
-        return packageBaseFrame.isLong(slot);
+        return getPackageBaseFrame().isLong(slot);
     }
 
     @Override
     public boolean isFloat(FrameSlot slot) {
-        return packageBaseFrame.isFloat(slot);
+        return getPackageBaseFrame().isFloat(slot);
     }
 
     @Override
     public boolean isDouble(FrameSlot slot) {
-        return packageBaseFrame.isDouble(slot);
+        return getPackageBaseFrame().isDouble(slot);
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
index 73cd91202969b72b24a7f5a7f0074caeb700dd04..6ed608da4e7391b7000bea7843bb4793918b5d9c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
@@ -28,6 +28,7 @@ import org.junit.Test;
 
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.api.vm.PolyglotEngine.Builder;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.tck.TruffleTCK;
 
@@ -94,8 +95,8 @@ public class FastRTckTest extends TruffleTCK {
     // @formatter:on
 
     @Override
-    protected PolyglotEngine prepareVM() throws Exception {
-        PolyglotEngine vm = PolyglotEngine.newBuilder().build();
+    protected PolyglotEngine prepareVM(Builder builder) throws Exception {
+        PolyglotEngine vm = builder.build();
         vm.eval(INITIALIZATION);
         return vm;
     }
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 20bb64bec355f05c33fbaca7b504e8af5ed6daca..88c6038de148099203dfed37dcc1a454b6f6f17b 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -434,8 +434,7 @@ def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
 def _simple_unit_tests():
-#    return ','.join(map(_test_subpackage, ['library.base', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'tck', 'parser', 'S4']))
-    return ','.join(map(_test_subpackage, ['library.base', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4']))
+    return ','.join(map(_test_subpackage, ['library.base', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'tck', 'parser', 'S4']))
 
 def _package_unit_tests():
     return ','.join(map(_test_subpackage, ['rffi', 'rpackages']))