diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
index 2d1259aef13953bb8228849bb260462a68d0ccc5..8f577b5e6ecba01b82b38d0b25895b0dc1f17976 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
@@ -39,7 +39,6 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "as.double", aliases = {"as.numeric"}, kind = PRIMITIVE, parameterNames = {"x", "..."})
-// TODO define alias in R
 public abstract class AsDouble extends RBuiltinNode {
 
     @Child private CastDoubleNode castDoubleNode;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
index bbecfeff67beae84e463616580632205d8616725..dc7f08b5a6b1d9c739d075192346568b16b2ccff 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
@@ -24,20 +24,18 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
 
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.InlineCacheNode;
-import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.MissingNodeGen.MissingCheckCacheNodeGen;
 import com.oracle.truffle.r.nodes.function.GetMissingValueNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.RMissingHelper;
@@ -51,27 +49,43 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 @RBuiltin(name = "missing", kind = PRIMITIVE, parameterNames = {"x"}, nonEvalArgs = 0)
 public abstract class Missing extends RBuiltinNode {
 
-    @Child private InlineCacheNode repCache;
+    public abstract static class MissingCheckCache extends Node {
 
-    private final ConditionProfile isSymbolNullProfile = ConditionProfile.createBinaryProfile();
+        protected static final int CACHE_LIMIT = 3;
 
-    private static InlineCacheNode createRepCache(int level) {
-        Function<String, RNode> reify = symbol -> createNodeForRep(symbol, level);
-        BiFunction<Frame, String, Object> generic = (frame, symbol) -> RRuntime.asLogical(RMissingHelper.isMissingArgument(frame, symbol));
-        return InlineCacheNode.createCache(3, reify, generic);
-    }
+        private final int level;
+
+        protected MissingCheckCache(int level) {
+            this.level = level;
+        }
+
+        public static MissingCheckCache create(int level) {
+            return MissingCheckCacheNodeGen.create(level);
+        }
+
+        public abstract boolean execute(Frame frame, String symbol);
+
+        protected MissingCheckLevel createNodeForRep(String symbol) {
+            return new MissingCheckLevel(symbol, level);
+        }
 
-    private static RNode createNodeForRep(String symbol, int level) {
-        if (symbol == null) {
-            return ConstantNode.create(RRuntime.LOGICAL_FALSE);
+        @Specialization(limit = "CACHE_LIMIT", guards = "cachedSymbol == symbol")
+        public static boolean checkCached(Frame frame, @SuppressWarnings("unused") String symbol, //
+                        @SuppressWarnings("unused") @Cached("symbol") String cachedSymbol, //
+                        @Cached("createNodeForRep(symbol)") MissingCheckLevel node) {
+            return node.execute(frame);
+        }
+
+        @Specialization(contains = "checkCached")
+        public static boolean check(Frame frame, String symbol) {
+            return RMissingHelper.isMissingArgument(frame, symbol);
         }
-        return new MissingCheckLevel(symbol, level);
     }
 
-    private static class MissingCheckLevel extends RNode {
+    protected static class MissingCheckLevel extends Node {
 
         @Child private GetMissingValueNode getMissingValue;
-        @Child private InlineCacheNode recursive;
+        @Child private MissingCheckCache recursive;
         @Child private PromiseHelperNode promiseHelper;
 
         @CompilationFinal private FrameDescriptor recursiveDesc;
@@ -87,18 +101,17 @@ public abstract class Missing extends RBuiltinNode {
             this.getMissingValue = GetMissingValueNode.create(symbol);
         }
 
-        @Override
-        public Object execute(VirtualFrame frame) {
+        public boolean execute(Frame frame) {
             // Read symbols value directly
             Object value = getMissingValue.execute(frame);
             if (isNullProfile.profile(value == null)) {
                 // In case we are not able to read the symbol in current frame: This is not an
                 // argument and thus return false
-                return RRuntime.LOGICAL_FALSE;
+                return false;
             }
 
             if (isMissingProfile.profile(RMissingHelper.isMissing(value))) {
-                return RRuntime.LOGICAL_TRUE;
+                return true;
             }
 
             // This might be a promise...
@@ -110,30 +123,30 @@ public abstract class Missing extends RBuiltinNode {
                     recursiveDesc = !promise.isEvaluated() && promise.getFrame() != null ? promise.getFrame().getFrameDescriptor() : null;
                 }
                 if (level == 0 && promiseHelper.isDefaultArgument(promise)) {
-                    return RRuntime.LOGICAL_TRUE;
+                    return true;
                 }
                 if (promiseHelper.isEvaluated(promise)) {
                     if (level > 0) {
-                        return RRuntime.LOGICAL_FALSE;
+                        return false;
                     }
                 } else {
                     // Check: If there is a cycle, return true. (This is done like in GNU R)
                     if (promiseHelper.isUnderEvaluation(promise)) {
-                        return RRuntime.LOGICAL_TRUE;
+                        return true;
                     }
                 }
                 String symbol = RMissingHelper.unwrapName((RNode) promise.getRep());
                 if (isSymbolNullProfile.profile(symbol == null)) {
-                    return RRuntime.LOGICAL_FALSE;
+                    return false;
                 } else {
                     if (recursiveDesc != null) {
                         promiseHelper.materialize(promise); // Ensure that promise holds a frame
                     }
                     if (recursiveDesc == null || recursiveDesc != promise.getFrame().getFrameDescriptor()) {
                         if (promiseHelper.isEvaluated(promise)) {
-                            return RRuntime.LOGICAL_FALSE;
+                            return false;
                         } else {
-                            return RRuntime.asLogical(RMissingHelper.isMissingName(promise));
+                            return RMissingHelper.isMissingName(promise);
                         }
                     } else {
                         if (recursiveDesc == null) {
@@ -144,7 +157,7 @@ public abstract class Missing extends RBuiltinNode {
                             promise.setState(PromiseState.UnderEvaluation);
                             if (recursive == null) {
                                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                                recursive = insert(createRepCache(level + 1));
+                                recursive = insert(MissingCheckCache.create(level + 1));
                             }
                             return recursive.execute(promise.getFrame(), symbol);
                         } finally {
@@ -153,18 +166,16 @@ public abstract class Missing extends RBuiltinNode {
                     }
                 }
             }
-            return RRuntime.LOGICAL_FALSE;
+            return false;
         }
     }
 
     @Specialization
-    protected byte missing(VirtualFrame frame, RPromise promise) {
-        if (repCache == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            repCache = insert(createRepCache(0));
-        }
+    protected byte missing(VirtualFrame frame, RPromise promise, //
+                    @Cached("create(0)") MissingCheckCache cache, //
+                    @Cached("createBinaryProfile()") ConditionProfile isNullSymbol) {
         String symbol = RMissingHelper.unwrapName((RNode) promise.getRep());
-        return isSymbolNullProfile.profile(symbol == null) ? RRuntime.LOGICAL_FALSE : (byte) repCache.execute(frame, symbol);
+        return RRuntime.asLogical(isNullSymbol.profile(symbol == null) ? false : cache.execute(frame, symbol));
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
index 3ee3407d913bb8b50740ce2c3ed1f473af9be59e..8d8c040afce1aafde176e50acc39673a9ba32e3c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
@@ -14,18 +14,20 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RBuiltinKind.SUBSTITUTE;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode;
+import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNodeGen;
+import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
+import com.oracle.truffle.r.nodes.attributes.PutAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.PutAttributeNodeGen;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
-import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -39,6 +41,12 @@ public abstract class Transpose extends RBuiltinNode {
 
     private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
     private final BranchProfile hasDimNamesProfile = BranchProfile.create();
+    private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile();
+
+    @Child private CopyOfRegAttributesNode copyRegAttributes = CopyOfRegAttributesNodeGen.create();
+    @Child private InitAttributesNode initAttributes = InitAttributesNode.create();
+    @Child private PutAttributeNode putDimensions = PutAttributeNodeGen.createDim();
+    @Child private PutAttributeNode putDimNames = PutAttributeNodeGen.createDimNames();
 
     public abstract Object execute(Object o);
 
@@ -63,100 +71,96 @@ public abstract class Transpose extends RBuiltinNode {
     }
 
     @Specialization(guards = "isEmpty2D(vector)")
-    @TruffleBoundary
     protected RAbstractVector transpose(RAbstractVector vector) {
         int[] dim = vector.getDimensions();
         return vector.copyWithNewDimensions(new int[]{dim[1], dim[0]});
     }
 
-    @Specialization(guards = "!isEmpty2D(vector)")
-    @TruffleBoundary
-    protected RIntVector transpose(RAbstractIntVector vector) {
-        return performAbstractIntVector(vector, vector.isMatrix() ? vector.getDimensions() : new int[]{vector.getLength(), 1});
+    @FunctionalInterface
+    private interface InnerLoop<T extends RAbstractVector> {
+        RVector apply(T vector, int firstDim);
     }
 
-    private RIntVector performAbstractIntVector(RAbstractIntVector vector, int[] dim) {
-        int firstDim = dim[0]; // rows
-        int secondDim = dim[1];
+    protected <T extends RAbstractVector> RVector transposeInternal(T vector, InnerLoop<T> innerLoop) {
+        int firstDim;
+        int secondDim;
+        if (isMatrixProfile.profile(vector.isMatrix())) {
+            firstDim = vector.getDimensions()[0];
+            secondDim = vector.getDimensions()[1];
+        } else {
+            firstDim = vector.getLength();
+            secondDim = 1;
+        }
+        RNode.reportWork(this, vector.getLength());
+
+        RVector r = innerLoop.apply(vector, firstDim);
+        // copy attributes
+        copyRegAttributes.execute(vector, r);
+        // set new dimensions
+        int[] newDim = new int[]{secondDim, firstDim};
+        r.setInternalDimensions(newDim);
+        putDimensions.execute(initAttributes.execute(r), RDataFactory.createIntVector(newDim, RDataFactory.COMPLETE_VECTOR));
+        // set new dim names
+        RList dimNames = vector.getDimNames(attrProfiles);
+        if (dimNames != null) {
+            hasDimNamesProfile.enter();
+            assert dimNames.getLength() == 2;
+            RList newDimNames = RDataFactory.createList(new Object[]{dimNames.getDataAt(1), dimNames.getDataAt(0)});
+            r.setInternalDimNames(newDimNames);
+            putDimNames.execute(r.getAttributes(), newDimNames);
+        }
+        return r;
+    }
+
+    private static RVector innerLoopInt(RAbstractIntVector vector, int firstDim) {
         int[] result = new int[vector.getLength()];
         int j = 0;
-
-        RNode.reportWork(this, vector.getLength());
         for (int i = 0; i < result.length; i++, j += firstDim) {
             if (j > (result.length - 1)) {
                 j -= (result.length - 1);
             }
             result[i] = vector.getDataAt(j);
         }
-        int[] newDim = new int[]{secondDim, firstDim};
-        RIntVector r = RDataFactory.createIntVector(result, vector.isComplete());
-        r.copyAttributesFrom(attrProfiles, vector);
-        r.setDimensions(newDim);
-        setDimNames(r, vector);
-        return r;
+        return RDataFactory.createIntVector(result, vector.isComplete());
     }
 
-    @Specialization(guards = "!isEmpty2D(vector)")
-    @TruffleBoundary
-    protected RDoubleVector transpose(RAbstractDoubleVector vector) {
-        return performAbstractDoubleVector(vector, vector.isMatrix() ? vector.getDimensions() : new int[]{vector.getLength(), 1});
-    }
-
-    private RDoubleVector performAbstractDoubleVector(RAbstractDoubleVector vector, int[] dim) {
-        int firstDim = dim[0];
-        int secondDim = dim[1];
+    private static RVector innerLoopDouble(RAbstractDoubleVector vector, int firstDim) {
         double[] result = new double[vector.getLength()];
         int j = 0;
-
-        RNode.reportWork(this, vector.getLength());
         for (int i = 0; i < result.length; i++, j += firstDim) {
             if (j > (result.length - 1)) {
                 j -= (result.length - 1);
             }
             result[i] = vector.getDataAt(j);
         }
-        int[] newDim = new int[]{secondDim, firstDim};
-        RDoubleVector r = RDataFactory.createDoubleVector(result, vector.isComplete());
-        r.copyAttributesFrom(attrProfiles, vector);
-        r.setDimensions(newDim);
-        setDimNames(r, vector);
-        return r;
-    }
-
-    @Specialization(guards = "!isEmpty2D(vector)")
-    @TruffleBoundary
-    protected RStringVector transpose(RAbstractStringVector vector) {
-        return performAbstractStringVector(vector, vector.isMatrix() ? vector.getDimensions() : new int[]{vector.getLength(), 1});
+        return RDataFactory.createDoubleVector(result, vector.isComplete());
     }
 
-    private RStringVector performAbstractStringVector(RAbstractStringVector vector, int[] dim) {
-        int firstDim = dim[0];
-        int secondDim = dim[1];
+    private static RVector innerLoopString(RAbstractStringVector vector, int firstDim) {
         String[] result = new String[vector.getLength()];
         int j = 0;
-
-        RNode.reportWork(this, vector.getLength());
         for (int i = 0; i < result.length; i++, j += firstDim) {
             if (j > (result.length - 1)) {
                 j -= (result.length - 1);
             }
             result[i] = vector.getDataAt(j);
         }
-        int[] newDim = new int[]{secondDim, firstDim};
-        RStringVector r = RDataFactory.createStringVector(result, vector.isComplete());
-        r.copyAttributesFrom(attrProfiles, vector);
-        r.setDimensions(newDim);
-        setDimNames(r, vector);
-        return r;
+        return RDataFactory.createStringVector(result, vector.isComplete());
     }
 
-    private void setDimNames(RVector newVector, RAbstractVector oldVector) {
-        RList dimNames = oldVector.getDimNames(attrProfiles);
-        if (dimNames != null) {
-            hasDimNamesProfile.enter();
-            assert dimNames.getLength() == 2;
-            newVector.setDimNames(RDataFactory.createList(new Object[]{dimNames.getDataAt(1), dimNames.getDataAt(0)}));
-        }
+    @Specialization(guards = "!isEmpty2D(vector)")
+    protected RVector transpose(RAbstractIntVector vector) {
+        return transposeInternal(vector, Transpose::innerLoopInt);
+    }
+
+    @Specialization(guards = "!isEmpty2D(vector)")
+    protected RVector transpose(RAbstractDoubleVector vector) {
+        return transposeInternal(vector, Transpose::innerLoopDouble);
+    }
+
+    @Specialization(guards = "!isEmpty2D(vector)")
+    protected RVector transpose(RAbstractStringVector vector) {
+        return transposeInternal(vector, Transpose::innerLoopString);
     }
 
     protected static boolean isEmpty2D(RAbstractVector vector) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
index 08725a78035513e5e75de37be68dae9a527edc79..82921e78731444b752b7bd5743d4d549345376a4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
@@ -118,8 +118,15 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
 
             @Override
             protected RSyntaxNode visit(RSyntaxFunction element) {
+                String assignedFrom = null;
+                if (element instanceof FunctionExpressionNode) {
+                    FunctionExpressionNode function = (FunctionExpressionNode) element;
+                    if (function.getParent() instanceof WriteVariableNode) {
+                        assignedFrom = ((WriteVariableNode) function.getParent()).getName().toString();
+                    }
+                }
                 ArrayList<Argument<RSyntaxNode>> params = createArguments(element.getSyntaxSignature(), element.getSyntaxArgumentDefaults());
-                return function(element.getSourceSection(), params, accept(element.getSyntaxBody()), null);
+                return function(element.getSourceSection(), params, accept(element.getSyntaxBody()), assignedFrom);
             }
         }.accept(original);
     }
@@ -210,8 +217,10 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
         return signature;
     }
 
-    private static String getFunctionDescription(SourceSection source, RSyntaxNode assignedTo) {
-        if (assignedTo instanceof RSyntaxLookup) {
+    private static String getFunctionDescription(SourceSection source, Object assignedTo) {
+        if (assignedTo instanceof String) {
+            return (String) assignedTo;
+        } else if (assignedTo instanceof RSyntaxLookup) {
             return ((RSyntaxLookup) assignedTo).getIdentifier();
         } else {
             String functionBody = source.getCode();
@@ -382,7 +391,7 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
     }
 
     @Override
-    public RSyntaxNode function(SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, RSyntaxNode assignedTo) {
+    public RSyntaxNode function(SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, Object assignedTo) {
         String description = getFunctionDescription(source, assignedTo);
         RootCallTarget callTarget = rootFunction(source, params, body, description);
         return FunctionExpressionNode.create(source, callTarget);
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 831e6a87db91e4521a947a2fd01e0bd54827913b..d9b138b73d4819b1379e3579944ad9ed6c3f6fd2 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
@@ -554,10 +554,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
                     evalPromiseSlowPathWithName(frame, (RPromise) lookup.getValue());
                 }
                 if (lookup != null) {
-                    if (lookup.getValue() == null) {
-                        return new LookupLevel(lookup);
-                    }
-                    if (checkTypeSlowPath(frame, lookup.getValue())) {
+                    if (lookup.getValue() == null || checkTypeSlowPath(frame, lookup.getValue())) {
                         return new LookupLevel(lookup);
                     }
                 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java
index 0f8a5f888010121e101d2a298c43f0f22ac3efcf..4f1a2ccad84568f50712f5df925f673209602a78 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java
@@ -52,6 +52,10 @@ public abstract class CopyAttributesNode extends RBaseNode {
         this.copyAllAttributes = copyAllAttributes;
     }
 
+    public static CopyAttributesNode createCopyAllAttributes() {
+        return CopyAttributesNodeGen.create(true);
+    }
+
     public abstract RAbstractVector execute(RAbstractVector target, RAbstractVector left, int leftLength, RAbstractVector right, int rightLength);
 
     protected boolean containsMetadata(RAbstractVector vector, RAttributeProfiles attrProfiles) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java
index 8645729bf27bc87c31bad5baa917fce21685d3ac..2d23acf57927a512e833f6c78ae86a06588a0af7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java
@@ -55,6 +55,10 @@ public abstract class PutAttributeNode extends RBaseNode {
         return PutAttributeNodeGen.create(RRuntime.DIM_ATTR_KEY);
     }
 
+    public static PutAttributeNode createDimNames() {
+        return PutAttributeNodeGen.create(RRuntime.DIMNAMES_ATTR_KEY);
+    }
+
     public abstract void execute(RAttributes attr, Object value);
 
     protected boolean nameMatches(RAttributes attr, int index) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
index f027b716164a47b23766b3abfbf56e57ade0c3cf..a45022312ca4653b6c161b8c0734e45354ef3108 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
@@ -24,27 +24,24 @@ package com.oracle.truffle.r.nodes.function;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.nodes.RNode;
 
 /**
  * A {@link ArgumentStatePush} is used to bump up state transition for function arguments.
  */
-@NodeChild(value = "op")
-public abstract class ArgumentStatePush extends RNode {
+public abstract class ArgumentStatePush extends Node {
 
-    public abstract Object executeObject(VirtualFrame frame, Object shareable);
+    public abstract void executeObject(VirtualFrame frame, Object shareable);
 
     private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile();
 
@@ -64,7 +61,8 @@ public abstract class ArgumentStatePush extends RNode {
         return mask > 0;
     }
 
-    private void transitionStateExp(VirtualFrame frame, RShareable shareable) {
+    @Specialization
+    public void transitionState(VirtualFrame frame, RShareable shareable) {
         if (isRefCountUpdateable.profile(!shareable.isSharedPermanent())) {
             shareable.incRefCount();
         }
@@ -114,14 +112,8 @@ public abstract class ArgumentStatePush extends RNode {
         }
     }
 
-    @Specialization
-    public RNull transitionState(VirtualFrame frame, RShareable shareable) {
-        transitionStateExp(frame, shareable);
-        return RNull.instance;
-    }
-
     @Specialization(guards = "!isShareable(o)")
-    public RNull transitionStateNonShareable(VirtualFrame frame, @SuppressWarnings("unused") Object o) {
+    public void transitionStateNonShareable(VirtualFrame frame, @SuppressWarnings("unused") Object o) {
         if (mask > 0) {
             // this argument used to be reference counted but is no longer
             CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -133,7 +125,6 @@ public abstract class ArgumentStatePush extends RNode {
             fdn.getArgPostProcess().transArgsBitSet = transArgsBitSet & (~mask);
             mask = -1;
         }
-        return RNull.instance;
     }
 
     protected boolean isShareable(Object o) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PreProcessArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PreProcessArgumentsNode.java
index c5fc1a9e8e732796256db437b4a8d74aa3b32f65..309d854b53d85b61c9bbadbd3b89ddadd8b54c95 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PreProcessArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PreProcessArgumentsNode.java
@@ -52,7 +52,7 @@ final class PreProcessArgumentsNode extends RNode {
     static PreProcessArgumentsNode create(int length) {
         ArgumentStatePush[] argStatePushNodes = new ArgumentStatePush[length];
         for (int i = 0; i < length; i++) {
-            argStatePushNodes[i] = ArgumentStatePushNodeGen.create(i, null);
+            argStatePushNodes[i] = ArgumentStatePushNodeGen.create(i);
         }
         return new PreProcessArgumentsNode(argStatePushNodes);
     }
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 51f811371e9c8bf5a3ffe2bc8f0cc7cc1a070403..12bc4b29ef23ec8e9c9bcd3c9b1ab3716c431ac6 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
@@ -127,7 +127,6 @@ public class PromiseHelperNode extends RBaseNode {
         }
     }
 
-    @Child private InlineCacheNode expressionInlineCache;
     @Child private InlineCacheNode promiseClosureCache;
 
     @Child private PromiseHelperNode nextNode = null;
@@ -176,26 +175,20 @@ public class PromiseHelperNode extends RBaseNode {
             throw RError.error(RError.SHOW_CALLER, RError.Message.PROMISE_CYCLE);
         }
         try {
+            if (promiseClosureCache == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                promiseClosureCache = insert(InlineCacheNode.createPromise(FastROptions.PromiseCacheSize.getNonNegativeIntValue()));
+            }
             if (isInOriginFrame(frame, promise)) {
                 // state change must happen inside of conditional as isInOriginalFrame checks the
                 // state
                 promise.setState(PromiseState.UnderEvaluation);
-                if (expressionInlineCache == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    expressionInlineCache = insert(InlineCacheNode.createExpression(FastROptions.PromiseCacheSize.getNonNegativeIntValue()));
-                }
-                return expressionInlineCache.execute(frame, promise.getRep());
+                return promiseClosureCache.execute(frame, promise.getClosure());
             } else {
                 promise.setState(PromiseState.UnderEvaluation);
                 Frame promiseFrame = promiseFrameProfile.profile(promise.getFrame());
                 assert promiseFrame != null;
-
-                if (promiseClosureCache == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    promiseClosureCache = insert(InlineCacheNode.createPromise(FastROptions.PromiseCacheSize.getNonNegativeIntValue()));
-                }
-                promiseFrame = wrapPromiseFrame(frame, promiseFrame);
-                return promiseClosureCache.execute(promiseFrame, promise.getClosure());
+                return promiseClosureCache.execute(wrapPromiseFrame(frame, promiseFrame), promise.getClosure());
             }
         } finally {
             promise.setState(state);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
index c6d3ff6620beb0ee4e1d2fe9ef1ef6e7a0d82448..7ed844a144758904c56d2f9e9463f19e2c1d3673 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
@@ -50,7 +50,7 @@ public final class WrapArgumentNode extends WrapArgumentBaseNode {
         super(operand, modeChange);
         this.modeChange = modeChange;
         this.index = index;
-        this.argPushStateNode = modeChange ? ArgumentStatePushNodeGen.create(index, null) : null;
+        this.argPushStateNode = modeChange ? ArgumentStatePushNodeGen.create(index) : null;
     }
 
     public boolean modeChange() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapDefaultArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapDefaultArgumentNode.java
index 903438fdc7430a941b14ef5c90f1102f4639d2be..0d9c02ebf52ab89c5fbf33243e42107d19b7c81b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapDefaultArgumentNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapDefaultArgumentNode.java
@@ -45,22 +45,16 @@ public final class WrapDefaultArgumentNode extends WrapArgumentBaseNode {
     @Override
     public Object execute(VirtualFrame frame) {
         Object result = operand.execute(frame);
-        return execute(result);
-    }
-
-    public Object execute(Object o) {
-        Object result = o;
         RShareable rShareable = getShareable(result);
         if (rShareable != null) {
             shareable.enter();
             if (isShared.profile(rShareable.isShared())) {
-                result = ((RShareable) o).copy();
+                return ((RShareable) result).copy();
             } else {
-                ((RShareable) o).incRefCount();
+                ((RShareable) result).incRefCount();
             }
         }
         return result;
-
     }
 
     public static RNode create(RNode operand) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index 7d19a9c479e82585435958ebdba4051a6da8f45e..c616637b9d65a548a3bbbaa1c7305a4c1e277e08 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -46,6 +46,7 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.StableValue;
+import com.oracle.truffle.r.runtime.data.RPromise;
 
 /**
  * This class maintains information about the current hierarchy of environments in the system. This
@@ -84,6 +85,7 @@ public final class FrameSlotChangeMonitor {
 
     private static final class StableValueLookupResult extends LookupResult {
         private final StableValue<Object> value;
+        @CompilationFinal private Object unwrappedValue;
 
         private StableValueLookupResult(String identifier, StableValue<Object> value) {
             super(identifier);
@@ -100,7 +102,20 @@ public final class FrameSlotChangeMonitor {
             assumption.check();
             StableValue<Object> result = value;
             result.getAssumption().check();
-            return result.getValue();
+            if (unwrappedValue == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                Object resultValue = result.getValue();
+                if (resultValue instanceof RPromise) {
+                    if (((RPromise) resultValue).isEvaluated()) {
+                        unwrappedValue = ((RPromise) resultValue).getValue();
+                    } else {
+                        return resultValue;
+                    }
+                } else {
+                    unwrappedValue = resultValue;
+                }
+            }
+            return unwrappedValue;
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
index dd1c9b2d6aa24ee5d21844f0044432f5f296f481..70a1f36cce9b345a234bab65335174a81b962505 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
@@ -89,7 +89,7 @@ public interface RCodeBuilder<T> {
      * names - if it is non-null, it represents the left hand side that this function is assigned
      * to.
      */
-    T function(SourceSection source, List<Argument<T>> arguments, T body, T assignedTo);
+    T function(SourceSection source, List<Argument<T>> arguments, T body, Object assignedTo);
 
     /**
      * Creates a new call target from a given function expression literal.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java
index b134d915c22729215a4a9a839cb06b9844196dc2..12918a1ed0ee2629f5a3919fd483bbc2c5dc28b7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java
@@ -16,7 +16,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG.RandomNumberGenerator;
 public abstract class RNGInitAdapter implements RandomNumberGenerator {
 
     // TODO: it seems like GNU R this is shared between the generators (does it matter?)
-    protected int[] iSeed = new int[625];
+    protected final int[] iSeed = new int[625];
 
     @Override
     public void setISeed(int[] seeds) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java
index 606bb90664f1d783f592afcafd5ecdd520929404..ddc4d8a7d864fc4e840ee814dcbaaea072e56167 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java
@@ -170,18 +170,26 @@ public final class MersenneTwister extends RNGInitAdapter {
         RInternalError.guarantee(localMti != N + 1);
 
         int pos = 0;
-        while (pos < count && localMti < N) {
-            int y = getMt(localMti++);
-            /* Tempering */
-            y ^= (y >>> 11);
-            y ^= (y << 7) & TEMPERING_MASK_B;
-            y ^= (y << 15) & TEMPERING_MASK_C;
-            y ^= (y >>> 18);
-            result[pos] = RRNG.fixup((y & 0xffffffffL) * RRNG.I2_32M1);
-            pos++;
-        }
+        while (true) {
+            int loopCount = Math.min(count - pos, N - localMti);
+            for (int i = 0; i < loopCount; i++) {
+                int y = getMt(localMti + i);
+                /* Tempering */
+                y ^= (y >>> 11);
+                y ^= (y << 7) & TEMPERING_MASK_B;
+                y ^= (y << 15) & TEMPERING_MASK_C;
+                y ^= (y >>> 18);
+                result[pos + i] = ((y + Integer.MIN_VALUE) - (double) Integer.MIN_VALUE) * RRNG.I2_32M1;
+            }
+            for (int i = 0; i < loopCount; i++) {
+                result[pos + i] = RRNG.fixup(result[pos + i]);
+            }
+            localMti += loopCount;
+            pos += loopCount;
 
-        while (pos < count) {
+            if (pos == count) {
+                break;
+            }
             /* generate N words at one time */
             int kk;
             for (kk = 0; kk < N - M; kk++) {
@@ -196,17 +204,6 @@ public final class MersenneTwister extends RNGInitAdapter {
             setMt(N - 1, getMt(M - 1) ^ (y2y >>> 1) ^ mag01(y2y & 0x1));
 
             localMti = 0;
-
-            while (pos < count && localMti < N) {
-                int y = getMt(localMti++);
-                /* Tempering */
-                y ^= (y >>> 11);
-                y ^= (y << 7) & TEMPERING_MASK_B;
-                y ^= (y << 15) & TEMPERING_MASK_C;
-                y ^= (y >>> 18);
-                result[pos] = RRNG.fixup((y & 0xffffffffL) * RRNG.I2_32M1);
-                pos++;
-            }
         }
         localDummy0 = localMti;
         mti = localMti;