protected override ICode VisitNewObj(ExprNewObj e)
        {
            var expr = this.HandleCall(e, (obj, args) => new ExprNewObj(e.Ctx, e.CallMethod, args));
            var res  = JsResolver.ResolveCallSite(expr);

            if (res == null)
            {
                return(expr);
            }
            else
            {
                return(this.Visit(res));
            }
        }
        protected override ICode VisitCall(ExprCall e)
        {
            var expr = this.HandleCall(e, (obj, args) => new ExprCall(e.Ctx, e.CallMethod, obj, args, e.IsVirtualCall, e.ConstrainedType, e.Type));
            var res  = JsResolver.ResolveCallSite(expr);

            if (res != null)
            {
                return(this.Visit(res));
            }
            if (expr.ConstrainedType != null)
            {
                if (expr.ConstrainedType.IsValueType)
                {
                    // Map constrained virtual call to a method on a value-type, to a non-virtual call.
                    // This is important as it prevents having to box the value-type, which is expensive
                    var impl = expr.ConstrainedType.EnumResolvedMethods().FirstOrDefault(x => x.MatchMethodOnly(expr.CallMethod));
                    if (impl != null)
                    {
                        var constrainedCall = new ExprCall(expr.Ctx, impl, expr.Obj, expr.Args, false, null, expr.Type);
                        return(constrainedCall);
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
            }
            if (expr.IsVirtualCall)
            {
                var ctx        = expr.Ctx;
                var objIsVar   = expr.Obj.IsVar();
                var temp       = objIsVar ? null : new ExprVarLocal(ctx, expr.Obj.Type);
                var getTypeObj = objIsVar ? expr.Obj : new ExprAssignment(ctx, temp, expr.Obj);
                var getType    = new ExprCall(ctx, typeof(object).GetMethod("GetType"), getTypeObj);
                var eJsVCall   = new ExprJsVirtualCall(ctx, expr.CallMethod, getType, temp ?? expr.Obj, expr.Args);
                return(eJsVCall);
            }
            return(expr);
        }