diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
index 64541106145dfabe334d6e23c28892c1e6c119cb..23b8ef26b78225307cc187d2d2cac36fba313196 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
@@ -22,27 +22,84 @@
  */
 package com.oracle.truffle.r.nodes;
 
-import java.util.*;
-import java.util.function.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.r.nodes.access.*;
-import com.oracle.truffle.r.nodes.access.variables.*;
-import com.oracle.truffle.r.nodes.binary.*;
-import com.oracle.truffle.r.nodes.control.*;
-import com.oracle.truffle.r.nodes.function.*;
-import com.oracle.truffle.r.parser.ast.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.BiFunction;
+
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.nodes.access.AccessArgumentNode;
+import com.oracle.truffle.r.nodes.access.ConstantNode;
+import com.oracle.truffle.r.nodes.access.ReadVariadicComponentNode;
+import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
+import com.oracle.truffle.r.nodes.access.WriteReplacementNode;
+import com.oracle.truffle.r.nodes.access.WriteVariableNode;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.binary.ColonNode;
+import com.oracle.truffle.r.nodes.control.BlockNode;
+import com.oracle.truffle.r.nodes.control.BreakNode;
+import com.oracle.truffle.r.nodes.control.ForNode;
+import com.oracle.truffle.r.nodes.control.IfNode;
+import com.oracle.truffle.r.nodes.control.NextNode;
+import com.oracle.truffle.r.nodes.control.ReplacementNode;
+import com.oracle.truffle.r.nodes.control.WhileNode;
+import com.oracle.truffle.r.nodes.function.FormalArguments;
+import com.oracle.truffle.r.nodes.function.FunctionBodyNode;
+import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
+import com.oracle.truffle.r.nodes.function.FunctionExpressionNode;
+import com.oracle.truffle.r.nodes.function.FunctionStatementsNode;
+import com.oracle.truffle.r.nodes.function.GroupDispatchNode;
+import com.oracle.truffle.r.nodes.function.PostProcessArgumentsNode;
+import com.oracle.truffle.r.nodes.function.RCallNode;
+import com.oracle.truffle.r.nodes.function.SaveArgumentsNode;
+import com.oracle.truffle.r.nodes.function.WrapDefaultArgumentNode;
+import com.oracle.truffle.r.parser.ast.ASTNode;
+import com.oracle.truffle.r.parser.ast.AccessVariable;
+import com.oracle.truffle.r.parser.ast.AccessVector;
+import com.oracle.truffle.r.parser.ast.ArgNode;
+import com.oracle.truffle.r.parser.ast.BinaryOperation;
+import com.oracle.truffle.r.parser.ast.Break;
+import com.oracle.truffle.r.parser.ast.Constant;
 import com.oracle.truffle.r.parser.ast.Constant.ConstantType;
-import com.oracle.truffle.r.parser.ast.Operation.ArithmeticOperator;
-import com.oracle.truffle.r.parser.ast.Operation.Operator;
+import com.oracle.truffle.r.parser.ast.FieldAccess;
+import com.oracle.truffle.r.parser.ast.For;
+import com.oracle.truffle.r.parser.ast.Formula;
 import com.oracle.truffle.r.parser.ast.Function;
-import com.oracle.truffle.r.parser.tools.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.env.frame.*;
-import com.oracle.truffle.r.runtime.nodes.*;
+import com.oracle.truffle.r.parser.ast.FunctionCall;
+import com.oracle.truffle.r.parser.ast.If;
+import com.oracle.truffle.r.parser.ast.Missing;
+import com.oracle.truffle.r.parser.ast.Next;
+import com.oracle.truffle.r.parser.ast.Operation.ArithmeticOperator;
+import com.oracle.truffle.r.parser.ast.Repeat;
+import com.oracle.truffle.r.parser.ast.Replacement;
+import com.oracle.truffle.r.parser.ast.Sequence;
+import com.oracle.truffle.r.parser.ast.SimpleAccessTempVariable;
+import com.oracle.truffle.r.parser.ast.SimpleAccessVariable;
+import com.oracle.truffle.r.parser.ast.SimpleAccessVariadicComponent;
+import com.oracle.truffle.r.parser.ast.SimpleAssignVariable;
+import com.oracle.truffle.r.parser.ast.UnaryOperation;
+import com.oracle.truffle.r.parser.ast.UpdateField;
+import com.oracle.truffle.r.parser.ast.UpdateVector;
+import com.oracle.truffle.r.parser.ast.While;
+import com.oracle.truffle.r.parser.tools.BasicVisitor;
+import com.oracle.truffle.r.parser.tools.EvaluatedArgumentsVisitor;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.FastROptions;
+import com.oracle.truffle.r.runtime.RGroupGenerics;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.FastPathFactory;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.REmpty;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> {
 
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 6a0941c5b4b62223e30e301112dc05457e28298a..425e5d847c6458a5f5243c83532305286a9bd866 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
@@ -190,9 +190,7 @@ public class RSerialize {
         protected Object addReadRef(Object item) {
             assert item != null;
             if (refTableIndex >= refTable.length) {
-                Object[] newRefTable = new Object[2 * refTable.length];
-                System.arraycopy(refTable, 0, newRefTable, 0, refTable.length);
-                refTable = newRefTable;
+                refTable = Arrays.copyOf(refTable, refTable.length * 2);
             }
             refTable[refTableIndex++] = item;
             return item;
@@ -416,15 +414,19 @@ public class RSerialize {
 
                     Object enclos = readItem();
                     REnvironment enclosing = enclos == RNull.instance ? REnvironment.baseEnv() : (REnvironment) enclos;
+                    final REnvironment.NewEnv env = RDataFactory.createNewEnv(enclosing, null);
+                    /*
+                     * We update the env reference as soon as possible, in case the contents of an
+                     * environment contain a reference to the env itself.
+                     */
+                    updateEnvReadRef(envRefTableIndex, env);
                     Object frame = readItem();
                     boolean hashed = frame == RNull.instance;
-                    REnvironment env;
                     Object hashtab = readItem();
                     if (hashed) {
-                        if (hashtab == RNull.instance) {
-                            env = RDataFactory.createNewEnv(enclosing, null);
-                        } else {
-                            env = RDataFactory.createNewEnv(enclosing, null, true, ((RList) hashtab).getLength());
+                        if (hashtab != RNull.instance) {
+                            env.setHashed(true);
+                            env.setInitialSize(((RList) hashtab).getLength());
                             RList hashList = (RList) hashtab;
                             // GnuR sizes its hash tables, empty slots indicated by RNull
                             for (int i = 0; i < hashList.getLength(); i++) {
@@ -437,14 +439,12 @@ public class RSerialize {
                             }
                         }
                     } else {
-                        env = RDataFactory.createNewEnv(enclosing, null);
                         while (frame != RNull.instance) {
                             RPairList pl = (RPairList) frame;
                             env.safePut(((RSymbol) pl.getTag()).getName(), pl.car());
                             frame = pl.cdr();
                         }
                     }
-                    updateEnvReadRef(envRefTableIndex, env);
                     if (locked != 0) {
                         env.lock(false);
                     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index 1014afa96b595033e3003ec30c2a079be6034e21..1c26f186889cae2f77521f15702933e5badeb83c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
@@ -437,15 +437,18 @@ public final class RDataFactory {
     }
 
     public static REnvironment createInternalEnv() {
-        return traceDataCreated(new REnvironment.NewEnv(null, RRuntime.createNonFunctionFrame().materialize(), REnvironment.UNNAMED, false, 0));
+        return traceDataCreated(new REnvironment.NewEnv(null, RRuntime.createNonFunctionFrame().materialize(), REnvironment.UNNAMED));
     }
 
-    public static REnvironment createNewEnv(REnvironment parent, String name) {
-        return traceDataCreated(new REnvironment.NewEnv(parent, RRuntime.createNonFunctionFrame().materialize(), name, false, 0));
+    public static REnvironment.NewEnv createNewEnv(REnvironment parent, String name) {
+        return traceDataCreated(new REnvironment.NewEnv(parent, RRuntime.createNonFunctionFrame().materialize(), name));
     }
 
-    public static REnvironment createNewEnv(REnvironment parent, String name, boolean hash, int size) {
-        return traceDataCreated(new REnvironment.NewEnv(parent, RRuntime.createNonFunctionFrame().materialize(), name, hash, size));
+    public static REnvironment createNewEnv(REnvironment parent, String name, boolean hashed, int initialSize) {
+        REnvironment.NewEnv env = new REnvironment.NewEnv(parent, RRuntime.createNonFunctionFrame().materialize(), name);
+        env.setHashed(hashed);
+        env.setInitialSize(initialSize);
+        return traceDataCreated(env);
     }
 
     public static RS4Object createS4Object() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
index db9575fff28277529841188da2761790dda20ef7..f6b6f3d4b914614496f5aefeea89a9dd86bf6354 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
@@ -487,7 +487,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa
 
     /**
      * Add name to namespace registry.
-     * 
+     *
      * @param name namespace name
      * @param env namespace value
      * @return {@code null} if name is already registered else {@code env}
@@ -504,7 +504,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa
 
     /**
      * Remove name from namespace registry.
-     * 
+     *
      * @param name namespace name
      * @return {@code null} if name is not registered else namespace value
      */
@@ -641,7 +641,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa
      */
     @TruffleBoundary
     public static REnvironment createFromList(RAttributeProfiles attrProfiles, RList list, REnvironment parent) {
-        REnvironment result = RDataFactory.createNewEnv(parent, null, false, 0);
+        REnvironment result = RDataFactory.createNewEnv(parent, null);
         RStringVector names = list.getNames(attrProfiles);
         for (int i = 0; i < list.getLength(); i++) {
             try {
@@ -980,13 +980,11 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa
      *
      */
     public static final class NewEnv extends REnvironment {
-        private final boolean hash;
-        private final int size;
+        private boolean hashed;
+        private int initialSize;
 
-        public NewEnv(REnvironment parent, MaterializedFrame frame, String name, boolean hash, int size) {
+        public NewEnv(REnvironment parent, MaterializedFrame frame, String name) {
             super(parent, UNNAMED, frame);
-            this.hash = hash;
-            this.size = size;
             if (parent != null) {
                 RArguments.setEnclosingFrame(frame, parent.getFrame());
             }
@@ -995,14 +993,21 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa
             }
         }
 
-        public boolean hashed() {
-            return hash;
+        public boolean isHashed() {
+            return hashed;
         }
 
-        public int createdSize() {
-            return size;
+        public void setHashed(boolean hashed) {
+            this.hashed = hashed;
         }
 
+        public int getInitialSize() {
+            return initialSize;
+        }
+
+        public void setInitialSize(int initialSize) {
+            this.initialSize = initialSize;
+        }
     }
 
     /**