Skip to content

Commit 2b5fa1d

Browse files
author
msftbot[bot]
authored
Merge pull request #41659 from CyrusNajmabadi/embeddedParsingStack
Reduce the amount of stack space needed for parsing embedded statements
2 parents edd063a + 2e04682 commit 2b5fa1d

File tree

1 file changed

+30
-20
lines changed

1 file changed

+30
-20
lines changed

src/Compilers/CSharp/Portable/Parser/LanguageParser.cs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections.Generic;
77
using System.Diagnostics;
8+
using System.Runtime.CompilerServices;
89
using System.Threading;
910
using Microsoft.CodeAnalysis.CSharp.Symbols;
1011
using Microsoft.CodeAnalysis.Text;
@@ -7146,35 +7147,44 @@ private bool IsEndOfFixedStatement()
71467147

71477148
private StatementSyntax ParseEmbeddedStatement()
71487149
{
7149-
// The consumers of embedded statements are expecting to receive a non-null statement
7150-
// yet there are several error conditions that can lead ParseStatementCore to return
7151-
// null. When that occurs create an error empty Statement and return it to the caller.
7152-
StatementSyntax statement = this.ParseStatementCore() ?? SyntaxFactory.EmptyStatement(EatToken(SyntaxKind.SemicolonToken));
7150+
// ParseEmbeddedStatement is called through many recursive statement parsing cases. We
7151+
// keep the body exceptionally simple, and we optimize for the common case, to ensure it
7152+
// is inlined into the callers. Otherwise the overhead of this single method can have a
7153+
// deep impact on the number of recursive calls we can make (more than a hundred during
7154+
// empirical testing).
71537155

7154-
switch (statement.Kind)
7156+
return parseEmbeddedStatementRest(this.ParseStatementCore());
7157+
7158+
StatementSyntax parseEmbeddedStatementRest(StatementSyntax statement)
71557159
{
7160+
if (statement == null)
7161+
{
7162+
// The consumers of embedded statements are expecting to receive a non-null statement
7163+
// yet there are several error conditions that can lead ParseStatementCore to return
7164+
// null. When that occurs create an error empty Statement and return it to the caller.
7165+
return SyntaxFactory.EmptyStatement(EatToken(SyntaxKind.SemicolonToken));
7166+
}
7167+
71567168
// In scripts, stand-alone expression statements may not be followed by semicolons.
71577169
// ParseExpressionStatement hides the error.
71587170
// However, embedded expression statements are required to be followed by semicolon.
7159-
case SyntaxKind.ExpressionStatement:
7160-
if (IsScript)
7161-
{
7162-
var expressionStatementSyntax = (ExpressionStatementSyntax)statement;
7163-
var semicolonToken = expressionStatementSyntax.SemicolonToken;
7171+
if (statement.Kind == SyntaxKind.ExpressionStatement &&
7172+
IsScript)
7173+
{
7174+
var expressionStatementSyntax = (ExpressionStatementSyntax)statement;
7175+
var semicolonToken = expressionStatementSyntax.SemicolonToken;
71647176

7165-
// Do not add a new error if the same error was already added.
7166-
if (semicolonToken.IsMissing &&
7167-
!semicolonToken.GetDiagnostics().Contains(diagnosticInfo => (ErrorCode)diagnosticInfo.Code == ErrorCode.ERR_SemicolonExpected))
7168-
{
7169-
semicolonToken = this.AddError(semicolonToken, ErrorCode.ERR_SemicolonExpected);
7170-
statement = expressionStatementSyntax.Update(expressionStatementSyntax.Expression, semicolonToken);
7171-
}
7177+
// Do not add a new error if the same error was already added.
7178+
if (semicolonToken.IsMissing &&
7179+
!semicolonToken.GetDiagnostics().Contains(diagnosticInfo => (ErrorCode)diagnosticInfo.Code == ErrorCode.ERR_SemicolonExpected))
7180+
{
7181+
semicolonToken = this.AddError(semicolonToken, ErrorCode.ERR_SemicolonExpected);
7182+
return expressionStatementSyntax.Update(expressionStatementSyntax.Expression, semicolonToken);
71727183
}
7184+
}
71737185

7174-
break;
7186+
return statement;
71757187
}
7176-
7177-
return statement;
71787188
}
71797189

71807190
private BreakStatementSyntax ParseBreakStatement()

0 commit comments

Comments
 (0)