Skip to content

Commit

Permalink
Don't track current field of state machines (#74216)
Browse files Browse the repository at this point in the history
Port of dotnet/linker#2979

Fixes #73048.

Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
  • Loading branch information
github-actions[bot] and MichalStrehovsky committed Aug 20, 2022
1 parent c7cab43 commit 37193fd
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ internal static bool IsStateMachineType(string typeName)
return typeName.Length > i + 1 && typeName[i + 1] == 'd';
}

internal static bool IsStateMachineCurrentField(string fieldName)
{
if (!IsGeneratedMemberName(fieldName))
return false;

int i = fieldName.LastIndexOf('>');
if (i == -1)
return false;

// Current field is <>2__current
return fieldName.Length > i + 1 && fieldName[i + 1] == '2';
}

internal static bool IsGeneratedType(string name) => IsStateMachineType(name) || IsLambdaDisplayClass(name);

internal static bool IsLambdaOrLocalFunction(string methodName) => IsLambdaMethod(methodName) || IsLocalFunction(methodName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,10 +500,17 @@ static IEnumerable<MetadataType> GetCompilerGeneratedNestedTypes(MetadataType ty

public static bool IsHoistedLocal(FieldDesc field)
{
// Treat all fields on compiler-generated types as hoisted locals.
// This avoids depending on the name mangling scheme for hoisted locals.
var declaringTypeName = field.OwningType.Name;
return CompilerGeneratedNames.IsLambdaDisplayClass(declaringTypeName) || CompilerGeneratedNames.IsStateMachineType(declaringTypeName);
if (CompilerGeneratedNames.IsLambdaDisplayClass(field.OwningType.Name))
return true;

if (CompilerGeneratedNames.IsStateMachineType(field.OwningType.Name))
{
// Don't track the "current" field which is used for state machine return values,
// because this can be expensive to track.
return !CompilerGeneratedNames.IsStateMachineCurrentField(field.Name);
}

return false;
}

// "Nested function" refers to lambdas and local functions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ internal static bool IsStateMachineType (string typeName)
return typeName.Length > i + 1 && typeName[i + 1] == 'd';
}

internal static bool IsStateMachineCurrentField (string fieldName)
{
if (!IsGeneratedMemberName (fieldName))
return false;

int i = fieldName.LastIndexOf ('>');
if (i == -1)
return false;

// Current field is <>2__current
return fieldName.Length > i + 1 && fieldName[i + 1] == '2';
}

internal static bool IsGeneratedType (string name) => IsStateMachineType (name) || IsLambdaDisplayClass (name);

internal static bool IsLambdaOrLocalFunction (string methodName) => IsLambdaMethod (methodName) || IsLocalFunction (methodName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,16 @@ static IEnumerable<TypeDefinition> GetCompilerGeneratedNestedTypes (TypeDefiniti

public static bool IsHoistedLocal (FieldDefinition field)
{
// Treat all fields on compiler-generated types as hoisted locals.
// This avoids depending on the name mangling scheme for hoisted locals.
var declaringTypeName = field.DeclaringType.Name;
return CompilerGeneratedNames.IsLambdaDisplayClass (declaringTypeName) || CompilerGeneratedNames.IsStateMachineType (declaringTypeName);
if (CompilerGeneratedNames.IsLambdaDisplayClass (field.DeclaringType.Name))
return true;

if (CompilerGeneratedNames.IsStateMachineType (field.DeclaringType.Name)) {
// Don't track the "current" field which is used for state machine return values,
// because this can be expensive to track.
return !CompilerGeneratedNames.IsStateMachineCurrentField (field.Name);
}

return false;
}

// "Nested function" refers to lambdas and local functions.
Expand Down

0 comments on commit 37193fd

Please sign in to comment.