diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
index 54ecf0b6dc9db4eaf3fcfd74062c55e6372bb18c..4cd34ed9f441d06c369bdfc1c72c98880a2d1d24 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerAsserts;
 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.Specialization;
 import com.oracle.truffle.api.frame.Frame;
@@ -89,21 +88,18 @@ public abstract class Lapply extends RBuiltinNode {
 
     private static final class ExtractElementInternal extends RSourceSectionNode implements RSyntaxCall {
 
-        protected ExtractElementInternal() {
+        @Child private ExtractVectorNode extractElementNode = ExtractVectorNodeGen.create(ElementAccessMode.SUBSCRIPT, false);
+        private final FrameSlot vectorSlot;
+        private final FrameSlot indexSlot;
+
+        protected ExtractElementInternal(FrameSlot vectorSlot, FrameSlot indexSlot) {
             super(RSyntaxNode.LAZY_DEPARSE);
+            this.vectorSlot = vectorSlot;
+            this.indexSlot = indexSlot;
         }
 
-        @Child private ExtractVectorNode extractElementNode = ExtractVectorNodeGen.create(ElementAccessMode.SUBSCRIPT, false);
-        @CompilationFinal private FrameSlot vectorSlot;
-        @CompilationFinal private FrameSlot indexSlot;
-
         @Override
         public Object execute(VirtualFrame frame) {
-            if (vectorSlot == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                vectorSlot = frame.getFrameDescriptor().findFrameSlot("X");
-                indexSlot = frame.getFrameDescriptor().findFrameSlot("i");
-            }
             try {
                 return extractElementNode.apply(frame, frame.getObject(vectorSlot), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE);
             } catch (FrameSlotTypeException e) {
@@ -149,8 +145,8 @@ public abstract class Lapply extends RBuiltinNode {
                         @Cached("createVectorSlot(frame)") FrameSlot vectorSlot, //
                         @Cached("create()") RLengthNode lengthNode, //
                         @Cached("createCountingProfile()") LoopConditionProfile loop, //
-                        @Cached("createCallNode()") RCallNode firstCallNode, //
-                        @Cached("createCallNode()") RCallNode callNode) {
+                        @Cached("createCallNode(vectorSlot, indexSlot)") RCallNode firstCallNode, //
+                        @Cached("createCallNode(vectorSlot, indexSlot)") RCallNode callNode) {
             // TODO: R switches to double if x.getLength() is greater than 2^31-1
             frame.setObject(vectorSlot, vector);
             int length = lengthNode.executeInteger(frame, vector);
@@ -171,10 +167,10 @@ public abstract class Lapply extends RBuiltinNode {
         /**
          * Creates the {@link RCallNode} for this target and {@code varArgs}.
          */
-        protected RCallNode createCallNode() {
+        protected RCallNode createCallNode(FrameSlot vectorSlot, FrameSlot indexSlot) {
             CompilerAsserts.neverPartOfCompilation();
 
-            ExtractElementInternal element = new ExtractElementInternal();
+            ExtractElementInternal element = new ExtractElementInternal(vectorSlot, indexSlot);
             ReadVariableNode readArgs = ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any);
 
             return RCallNode.createCall(createCallSourceSection(), ReadVariableNode.create("FUN"), ArgumentsSignature.get(null, "..."), element, readArgs);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
index 00fd37061cd9548111df37b17ddf621dea0401ca..3a3f0fe6d7477ce2aa7426dd4c7ae506f7867b8e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.binary;
 
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
@@ -65,26 +64,19 @@ public abstract class BinaryBooleanScalarNode extends RBuiltinNode {
 
     BinaryBooleanScalarNode(BooleanOperationFactory factory) {
         this.booleanLogic = factory.createOperation();
+        logic = new BinaryMapBooleanFunctionNode(booleanLogic);
+        leftCast = LogicalScalarCastNodeGen.create(booleanLogic.opName(), "x", logic.getLeftNACheck());
+        leftBox = BoxPrimitiveNodeGen.create();
+        rightCast = LogicalScalarCastNodeGen.create(booleanLogic.opName(), "y", logic.getRightNACheck());
+        rightBox = BoxPrimitiveNodeGen.create();
+        promiseHelper = new PromiseCheckHelperNode();
     }
 
     @Specialization
     protected byte binary(VirtualFrame frame, Object leftValue, Object rightValue) {
-        if (leftCast == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            logic = insert(new BinaryMapBooleanFunctionNode(booleanLogic));
-            leftCast = insert(LogicalScalarCastNodeGen.create(booleanLogic.opName(), "x", logic.getLeftNACheck()));
-            leftBox = insert(BoxPrimitiveNodeGen.create());
-        }
         byte left = leftCast.executeCast(leftBox.execute(leftValue));
         if (profile.profile(logic.requiresRightOperand(left))) {
-            if (rightCast == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                rightCast = insert(LogicalScalarCastNodeGen.create(booleanLogic.opName(), "y", logic.getRightNACheck()));
-                rightBox = insert(BoxPrimitiveNodeGen.create());
-                promiseHelper = insert(new PromiseCheckHelperNode());
-            }
-            byte right = rightCast.executeCast(rightBox.execute(promiseHelper.checkEvaluate(frame, rightValue)));
-            return logic.applyLogical(left, right);
+            return logic.applyLogical(left, rightCast.executeCast(rightBox.execute(promiseHelper.checkEvaluate(frame, rightValue))));
         }
         return left;
     }
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 4a2c89ad48a62fc5debd7c6be8f4bb3ca2864f8e..2e3030709b306ecc445d7a5bdf376c11bf1ea4f5 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
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.RootCallTarget;
 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.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
@@ -101,24 +102,13 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
     private final BranchProfile breakProfile = BranchProfile.create();
     private final BranchProfile nextProfile = BranchProfile.create();
 
-    @CompilationFinal private BranchProfile invalidateFrameSlotProfile;
-    // S3/S4 slots
-    @Child private FrameSlotNode dotGenericSlot;
-    @Child private FrameSlotNode dotMethodSlot;
-    // S3 slots
-    @Child private FrameSlotNode dotClassSlot;
-    @Child private FrameSlotNode dotGenericCallEnvSlot;
-    @Child private FrameSlotNode dotGenericCallDefSlot;
-    @Child private FrameSlotNode dotGroupSlot;
-    // S4 slots
-    @Child private FrameSlotNode dotDefinedSlot;
-    @Child private FrameSlotNode dotTargetSlot;
-    @Child private FrameSlotNode dotMethodsSlot;
-
     @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
     @Child private PostProcessArgumentsNode argPostProcess;
 
+    @Child private SetupS3ArgsNode setupS3Args;
+    @Child private SetupS4ArgsNode setupS4Args;
+
     private final boolean needsSplitting;
 
     @CompilationFinal private boolean containsDispatch;
@@ -317,55 +307,88 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         }
     }
 
+    private abstract static class SetupDispatchNode extends Node {
+        // S3/S4 slots
+        private final FrameSlot dotGenericSlot;
+        private final FrameSlot dotMethodSlot;
+
+        final BranchProfile invalidateFrameSlotProfile = BranchProfile.create();
+
+        SetupDispatchNode(FrameDescriptor frameDescriptor) {
+            dotGenericSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_GENERIC, FrameSlotKind.Object);
+            dotMethodSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_METHOD, FrameSlotKind.Object);
+        }
+
+        void execute(VirtualFrame frame, DispatchArgs args) {
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericSlot, args.generic, false, invalidateFrameSlotProfile);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotMethodSlot, args.method, false, invalidateFrameSlotProfile);
+        }
+    }
+
+    private static final class SetupS3ArgsNode extends SetupDispatchNode {
+        // S3 slots
+        private final FrameSlot dotClassSlot;
+        private final FrameSlot dotGenericCallEnvSlot;
+        private final FrameSlot dotGenericCallDefSlot;
+        private final FrameSlot dotGroupSlot;
+
+        SetupS3ArgsNode(FrameDescriptor frameDescriptor) {
+            super(frameDescriptor);
+            dotClassSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_CLASS, FrameSlotKind.Object);
+            dotGenericCallEnvSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_GENERIC_CALL_ENV, FrameSlotKind.Object);
+            dotGenericCallDefSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_GENERIC_DEF_ENV, FrameSlotKind.Object);
+            dotGroupSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_GROUP, FrameSlotKind.Object);
+        }
+
+        void execute(VirtualFrame frame, S3Args args) {
+            super.execute(frame, args);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotClassSlot, args.clazz, false, invalidateFrameSlotProfile);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericCallEnvSlot, args.callEnv, false, invalidateFrameSlotProfile);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericCallDefSlot, args.defEnv, false, invalidateFrameSlotProfile);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGroupSlot, args.group, false, invalidateFrameSlotProfile);
+        }
+    }
+
+    private static final class SetupS4ArgsNode extends SetupDispatchNode {
+        // S4 slots
+        private final FrameSlot dotDefinedSlot;
+        private final FrameSlot dotTargetSlot;
+        private final FrameSlot dotMethodsSlot;
+
+        SetupS4ArgsNode(FrameDescriptor frameDescriptor) {
+            super(frameDescriptor);
+            dotDefinedSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_DEFINED, FrameSlotKind.Object);
+            dotTargetSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_TARGET, FrameSlotKind.Object);
+            dotMethodsSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, RRuntime.R_DOT_METHODS, FrameSlotKind.Object);
+        }
+
+        void execute(VirtualFrame frame, S4Args args) {
+            super.execute(frame, args);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotDefinedSlot, args.defined, false, invalidateFrameSlotProfile);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotTargetSlot, args.target, false, invalidateFrameSlotProfile);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotMethodsSlot, args.methods, false, invalidateFrameSlotProfile);
+        }
+    }
+
     private void setupDispatchSlots(VirtualFrame frame) {
         DispatchArgs dispatchArgs = RArguments.getDispatchArgs(frame);
         if (dispatchArgs == null) {
             return;
         }
-        if (dotGenericSlot == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            assert invalidateFrameSlotProfile == null && dotMethodSlot == null;
-            invalidateFrameSlotProfile = BranchProfile.create();
-            FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
-
-            dotGenericSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_GENERIC, true));
-            dotMethodSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_METHOD, true));
-        }
-        FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericSlot.executeFrameSlot(frame), dispatchArgs.generic, false, invalidateFrameSlotProfile);
-        FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotMethodSlot.executeFrameSlot(frame), dispatchArgs.method, false, invalidateFrameSlotProfile);
-
         if (dispatchArgs instanceof S3Args) {
             S3Args s3Args = (S3Args) dispatchArgs;
-            if (dotClassSlot == null) {
+            if (setupS3Args == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                assert dotGenericCallEnvSlot == null && dotGenericCallDefSlot == null && dotGroupSlot == null;
-                invalidateFrameSlotProfile = BranchProfile.create();
-                FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
-
-                dotClassSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_CLASS, true));
-                dotGenericCallEnvSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_GENERIC_CALL_ENV, true));
-                dotGenericCallDefSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_GENERIC_DEF_ENV, true));
-                dotGroupSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_GROUP, true));
+                setupS3Args = insert(new SetupS3ArgsNode(frame.getFrameDescriptor()));
             }
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotClassSlot.executeFrameSlot(frame), s3Args.clazz, false, invalidateFrameSlotProfile);
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericCallEnvSlot.executeFrameSlot(frame), s3Args.callEnv, false, invalidateFrameSlotProfile);
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericCallDefSlot.executeFrameSlot(frame), s3Args.defEnv, false, invalidateFrameSlotProfile);
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGroupSlot.executeFrameSlot(frame), s3Args.group, false, invalidateFrameSlotProfile);
+            setupS3Args.execute(frame, s3Args);
         } else {
             S4Args s4Args = (S4Args) dispatchArgs;
-            if (dotDefinedSlot == null) {
+            if (setupS4Args == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                assert dotTargetSlot == null && dotMethodsSlot == null;
-                invalidateFrameSlotProfile = BranchProfile.create();
-                FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
-
-                dotDefinedSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_DEFINED, true));
-                dotTargetSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_TARGET, true));
-                dotMethodsSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_METHODS, true));
+                setupS4Args = insert(new SetupS4ArgsNode(frame.getFrameDescriptor()));
             }
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotDefinedSlot.executeFrameSlot(frame), s4Args.defined, false, invalidateFrameSlotProfile);
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotTargetSlot.executeFrameSlot(frame), s4Args.target, false, invalidateFrameSlotProfile);
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotMethodsSlot.executeFrameSlot(frame), s4Args.methods, false, invalidateFrameSlotProfile);
+            setupS4Args.execute(frame, s4Args);
         }
     }