Move dynamic handling out of Binary::DoResolve to reduce stack size
authorMarek Safar <marek.safar@gmail.com>
Fri, 13 Sep 2013 16:55:09 +0000 (18:55 +0200)
committerMarek Safar <marek.safar@gmail.com>
Fri, 13 Sep 2013 16:55:47 +0000 (18:55 +0200)
mcs/mcs/expression.cs

index 6216e173dddbc3b2fab6fecf884d5936c35fc6db..f21fba77c75f353be33d2816b0ba6f0daeeb889f 100644 (file)
@@ -3258,80 +3258,84 @@ namespace Mono.CSharp
                                CheckOutOfRangeComparison (ec, rc, left.Type);
                        }
 
-                       if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic || right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
-                               var lt = left.Type;
-                               var rt = right.Type;
-                               if (lt.Kind == MemberKind.Void || lt == InternalType.MethodGroup || lt == InternalType.AnonymousMethod ||
-                                       rt.Kind == MemberKind.Void || rt == InternalType.MethodGroup || rt == InternalType.AnonymousMethod) {
-                                       Error_OperatorCannotBeApplied (ec, left, right);
-                                       return null;
-                               }
+                       if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic || right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
+                               return DoResolveDynamic (ec);
 
-                               Arguments args;
+                       return DoResolveCore (ec, left, right);
+               }
 
-                               //
-                               // Special handling for logical boolean operators which require rhs not to be
-                               // evaluated based on lhs value
-                               //
-                               if ((oper & Operator.LogicalMask) != 0) {
-                                       Expression cond_left, cond_right, expr;
+               Expression DoResolveDynamic (ResolveContext rc)
+               {
+                       var lt = left.Type;
+                       var rt = right.Type;
+                       if (lt.Kind == MemberKind.Void || lt == InternalType.MethodGroup || lt == InternalType.AnonymousMethod ||
+                               rt.Kind == MemberKind.Void || rt == InternalType.MethodGroup || rt == InternalType.AnonymousMethod) {
+                               Error_OperatorCannotBeApplied (rc, left, right);
+                               return null;
+                       }
 
-                                       args = new Arguments (2);
+                       Arguments args;
 
-                                       if (lt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
-                                               LocalVariable temp = LocalVariable.CreateCompilerGenerated (lt, ec.CurrentBlock, loc);
+                       //
+                       // Special handling for logical boolean operators which require rhs not to be
+                       // evaluated based on lhs value
+                       //
+                       if ((oper & Operator.LogicalMask) != 0) {
+                               Expression cond_left, cond_right, expr;
 
-                                               var cond_args = new Arguments (1);
-                                               cond_args.Add (new Argument (new SimpleAssign (temp.CreateReferenceExpression (ec, loc), left).Resolve (ec)));
+                               args = new Arguments (2);
 
-                                               //
-                                               // dynamic && bool => IsFalse (temp = left) ? temp : temp && right;
-                                               // dynamic || bool => IsTrue (temp = left) ? temp : temp || right;
-                                               //
-                                               left = temp.CreateReferenceExpression (ec, loc);
-                                               if (oper == Operator.LogicalAnd) {
-                                                       expr = DynamicUnaryConversion.CreateIsFalse (ec, cond_args, loc);
-                                                       cond_left = left;
-                                               } else {
-                                                       expr = DynamicUnaryConversion.CreateIsTrue (ec, cond_args, loc);
-                                                       cond_left = left;
-                                               }
+                               if (lt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
+                                       LocalVariable temp = LocalVariable.CreateCompilerGenerated (lt, rc.CurrentBlock, loc);
+
+                                       var cond_args = new Arguments (1);
+                                       cond_args.Add (new Argument (new SimpleAssign (temp.CreateReferenceExpression (rc, loc), left).Resolve (rc)));
 
-                                               args.Add (new Argument (left));
-                                               args.Add (new Argument (right));
-                                               cond_right = new DynamicExpressionStatement (this, args, loc);
+                                       //
+                                       // dynamic && bool => IsFalse (temp = left) ? temp : temp && right;
+                                       // dynamic || bool => IsTrue (temp = left) ? temp : temp || right;
+                                       //
+                                       left = temp.CreateReferenceExpression (rc, loc);
+                                       if (oper == Operator.LogicalAnd) {
+                                               expr = DynamicUnaryConversion.CreateIsFalse (rc, cond_args, loc);
+                                               cond_left = left;
                                        } else {
-                                               LocalVariable temp = LocalVariable.CreateCompilerGenerated (ec.BuiltinTypes.Bool, ec.CurrentBlock, loc);
+                                               expr = DynamicUnaryConversion.CreateIsTrue (rc, cond_args, loc);
+                                               cond_left = left;
+                                       }
 
-                                               args.Add (new Argument (temp.CreateReferenceExpression (ec, loc).Resolve (ec)));
-                                               args.Add (new Argument (right));
-                                               right = new DynamicExpressionStatement (this, args, loc);
+                                       args.Add (new Argument (left));
+                                       args.Add (new Argument (right));
+                                       cond_right = new DynamicExpressionStatement (this, args, loc);
+                               } else {
+                                       LocalVariable temp = LocalVariable.CreateCompilerGenerated (rc.BuiltinTypes.Bool, rc.CurrentBlock, loc);
 
-                                               //
-                                               // bool && dynamic => (temp = left) ? temp && right : temp;
-                                               // bool || dynamic => (temp = left) ? temp : temp || right;
-                                               //
-                                               if (oper == Operator.LogicalAnd) {
-                                                       cond_left = right;
-                                                       cond_right = temp.CreateReferenceExpression (ec, loc);
-                                               } else {
-                                                       cond_left = temp.CreateReferenceExpression (ec, loc);
-                                                       cond_right = right;
-                                               }
+                                       args.Add (new Argument (temp.CreateReferenceExpression (rc, loc).Resolve (rc)));
+                                       args.Add (new Argument (right));
+                                       right = new DynamicExpressionStatement (this, args, loc);
 
-                                               expr = new BooleanExpression (new SimpleAssign (temp.CreateReferenceExpression (ec, loc), left));
+                                       //
+                                       // bool && dynamic => (temp = left) ? temp && right : temp;
+                                       // bool || dynamic => (temp = left) ? temp : temp || right;
+                                       //
+                                       if (oper == Operator.LogicalAnd) {
+                                               cond_left = right;
+                                               cond_right = temp.CreateReferenceExpression (rc, loc);
+                                       } else {
+                                               cond_left = temp.CreateReferenceExpression (rc, loc);
+                                               cond_right = right;
                                        }
 
-                                       return new Conditional (expr, cond_left, cond_right, loc).Resolve (ec);
+                                       expr = new BooleanExpression (new SimpleAssign (temp.CreateReferenceExpression (rc, loc), left));
                                }
 
-                               args = new Arguments (2);
-                               args.Add (new Argument (left));
-                               args.Add (new Argument (right));
-                               return new DynamicExpressionStatement (this, args, loc).Resolve (ec);
+                               return new Conditional (expr, cond_left, cond_right, loc).Resolve (rc);
                        }
 
-                       return DoResolveCore (ec, left, right);
+                       args = new Arguments (2);
+                       args.Add (new Argument (left));
+                       args.Add (new Argument (right));
+                       return new DynamicExpressionStatement (this, args, loc).Resolve (rc);
                }
 
                Expression DoResolveCore (ResolveContext ec, Expression left_orig, Expression right_orig)