diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
index e58454418aaec752705161e80ef211b976375550..b1055e6c04e64bdfd938ddecef7a6e5117fa9af0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
@@ -17,8 +17,8 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.foreign;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-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.interop.TruffleObject;
@@ -44,6 +44,11 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 @RBuiltin(name = "@", kind = PRIMITIVE, parameterNames = {"", ""}, nonEvalArgs = 1, behavior = COMPLEX)
 public abstract class Slot extends RBuiltinNode.Arg2 {
 
+    private static final int UNINITIALIZED = 0;
+    private static final int IS_LHS = 1;
+    private static final int IS_NOT_LHS = 2;
+
+    @CompilationFinal private int isLhsState = UNINITIALIZED;
     @Child private UpdateShareableChildValueNode sharedAttrUpdate = UpdateShareableChildValueNode.create();
     @Child private AccessSlotNode accessSlotNode = AccessSlotNodeGen.create(true);
 
@@ -71,24 +76,28 @@ public abstract class Slot extends RBuiltinNode.Arg2 {
         return unwrapParent instanceof RSyntaxCall && ((RSyntaxCall) unwrapParent).getSyntaxLHS() == n;
     }
 
-    protected boolean isForeignObject(Object obj) {
-        return RRuntime.isForeignObject(obj);
+    private boolean isLhsOfCall() {
+        if (isLhsState == UNINITIALIZED) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            Node unwrapParent = RASTUtils.unwrapParent(this);
+            assert ((BuiltinCallNode) unwrapParent).getBuiltin() == this;
+            if (unwrapParent instanceof BuiltinCallNode && isLhsOfSyntaxCall(((RBaseNode) unwrapParent).asRSyntaxNode())) {
+                isLhsState = IS_LHS;
+            } else {
+                isLhsState = IS_NOT_LHS;
+            }
+        }
+        return isLhsState == IS_LHS;
     }
 
-    protected boolean isLhsOfCall() {
-        CompilerAsserts.neverPartOfCompilation();
-        Node unwrapParent = RASTUtils.unwrapParent(this);
-        assert ((BuiltinCallNode) unwrapParent).getBuiltin() == this;
-        return unwrapParent instanceof BuiltinCallNode && isLhsOfSyntaxCall(((RBaseNode) unwrapParent).asRSyntaxNode());
+    protected boolean isLhsOfForeignCall(Object o) {
+        return RRuntime.isForeignObject(o) && isLhsOfCall();
     }
 
-    @Specialization(guards = {"isForeignObject(object)", "lhsOfCall"})
+    @Specialization(guards = "isLhsOfForeignCall(object)")
     protected Object getSlot(TruffleObject object, Object nameObj,
-                    @Cached("isLhsOfCall()") boolean lhsOfCall,
                     @Cached("createClassProfile()") ValueProfile nameObjProfile) {
 
-        assert lhsOfCall;
-
         String name = getName(nameObjProfile.profile(nameObj));
         assert Utils.isInterned(name);
 
@@ -96,7 +105,7 @@ public abstract class Slot extends RBuiltinNode.Arg2 {
         return RCallNode.createDeferredMemberAccess(object, name);
     }
 
-    @Specialization
+    @Specialization(guards = "!isLhsOfForeignCall(object)")
     protected Object getSlot(Object object, Object nameObj,
                     @Cached("createClassProfile()") ValueProfile nameObjProfile) {
         String name = getName(nameObjProfile.profile(nameObj));