dotnet/roslyn

Possibly improved code-gen for "typeswitch"

gafter opened this issue · 4 comments

We occasionally use a "typeswitch-style" switch in Roslyn. For example

        public static bool FormattingHelpers.IsCloseParenInStatement(this SyntaxToken token)
        {
            var statement = token.Parent as StatementSyntax;
            if (statement == null)
            {
                return false;
            }

            switch (statement)
            {
                case IfStatementSyntax ifStatement:
                    return ifStatement.CloseParenToken.Equals(token);
                case SwitchStatementSyntax switchStatement:
                    return switchStatement.CloseParenToken.Equals(token);
                case WhileStatementSyntax whileStatement:
                    return whileStatement.CloseParenToken.Equals(token);
                case DoStatementSyntax doStatement:
                    return doStatement.CloseParenToken.Equals(token);
                case ForStatementSyntax forStatement:
                    return forStatement.CloseParenToken.Equals(token);
                case CommonForEachStatementSyntax foreachStatement:
                    return foreachStatement.CloseParenToken.Equals(token);
                case LockStatementSyntax lockStatement:
                    return lockStatement.CloseParenToken.Equals(token);
                case UsingStatementSyntax usingStatement:
                    return usingStatement.CloseParenToken.Equals(token);
                case FixedStatementSyntax fixedStatement:
                    return fixedStatement.CloseParenToken.Equals(token);
            }

            return false;
        }

The generated code might possibly be improved by calling GetType() on the input and including a sequence of tests against the type desired (when consecutive tests are for sealed types).

We would have to measure whether we actually get any improvement before committing to such an optimization.

I agree that the jit does a pretty good job. For more than about 20 types in a type switch, we can use a hashtable to implement it more efficiently. See https://github.com/gafter/TypeSwitch/blob/master/TypeSwitch/TypeSwitchDispatch.cs for one approach.

Improved the prototype library so that the break-even point for using a hashtable is about 10 types in a switch. See https://github.com/gafter/TypeSwitch/blob/master/TypeSwitch/TypeSwitchDispatch.cs

Instead of the optimization discussed, we are planning to provide an API along the lines of https://github.com/dotnet/corefx/issues/36132 and use that in the compiler for efficient dispatch on type.