Skip to content

Commit cc72ecb

Browse files
committed
Remove MightContainReferences
1 parent 1e8cb7e commit cc72ecb

File tree

5 files changed

+242
-272
lines changed

5 files changed

+242
-272
lines changed

src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -422,31 +422,16 @@ internal static bool TryUnwrapBoundStateMachineScope(ref BoundStatement statemen
422422
return false;
423423
}
424424

425-
private void AddVariableCleanup(ArrayBuilder<BoundExpression> cleanup, FieldSymbol field)
426-
{
427-
if (MightContainReferences(field.Type))
428-
{
429-
cleanup.Add(F.AssignmentExpression(F.Field(F.This(), field), F.NullOrDefault(field.Type)));
430-
}
431-
}
432-
433425
/// <summary>
434-
/// Might the given type be, or contain, managed references? This is used to determine which
435-
/// fields allocated to temporaries should be cleared when the underlying variable goes out of scope, so
426+
/// Clear fields allocated to temporaries when the underlying variable goes out of scope, so
436427
/// that they do not cause unnecessary object retention.
437428
/// </summary>
438-
private bool MightContainReferences(TypeSymbol type)
429+
private void AddVariableCleanup(ArrayBuilder<BoundExpression> cleanup, FieldSymbol field)
439430
{
440-
if (type.IsReferenceType || type.TypeKind == TypeKind.TypeParameter) return true; // type parameter or reference type
441-
if (type.TypeKind != TypeKind.Struct) return false; // enums, etc
442-
if (type.SpecialType == SpecialType.System_TypedReference) return true;
443-
if (type.SpecialType.CanOptimizeBehavior()) return false; // int, etc
444-
if (!type.IsFromCompilation(this.CompilationState.ModuleBuilderOpt.Compilation)) return true; // perhaps from ref assembly
445-
foreach (var f in _emptyStructTypeCache.GetStructInstanceFields(type))
431+
if (field.Type.IsManagedTypeNoUseSiteDiagnostics)
446432
{
447-
if (MightContainReferences(f.Type)) return true;
433+
cleanup.Add(F.AssignmentExpression(F.Field(F.This(), field), F.NullOrDefault(field.Type)));
448434
}
449-
return false;
450435
}
451436

452437
private StateMachineFieldSymbol GetOrAllocateReusableHoistedField(TypeSymbol type, out bool reused, LocalSymbol local = null)

src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs

Lines changed: 115 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -10104,12 +10104,12 @@ public static async System.Collections.Generic.IAsyncEnumerable<int> Produce(boo
1010410104
}
1010510105
""";
1010610106
// Note: hoisted nested local gets cleared when exiting nested scope normally
10107-
var verifier = CompileAndVerify(src, expectedOutput: ExpectedOutput("420"), references: [libComp.EmitToImageReference()],
10107+
var verifier = CompileAndVerify(src, expectedOutput: ExpectedOutput("4242"), references: [libComp.EmitToImageReference()],
1010810108
verify: Verification.Skipped, targetFramework: TargetFramework.Net80).VerifyDiagnostics();
1010910109

1011010110
verifier.VerifyIL("C.<Produce>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", """
1011110111
{
10112-
// Code size 449 (0x1c1)
10112+
// Code size 437 (0x1b5)
1011310113
.maxstack 3
1011410114
.locals init (int V_0,
1011510115
S V_1,
@@ -10125,23 +10125,23 @@ .locals init (int V_0,
1012510125
IL_0008: ldc.i4.s -6
1012610126
IL_000a: sub
1012710127
IL_000b: switch (
10128-
IL_0150,
10129-
IL_00c9,
10128+
IL_0144,
10129+
IL_00bd,
1013010130
IL_0072,
1013110131
IL_002c,
1013210132
IL_002c,
1013310133
IL_002c,
10134-
IL_011a)
10134+
IL_010e)
1013510135
IL_002c: ldarg.0
1013610136
IL_002d: ldfld "bool C.<Produce>d__0.<>w__disposeMode"
1013710137
IL_0032: brfalse.s IL_0039
10138-
IL_0034: leave IL_018d
10138+
IL_0034: leave IL_0181
1013910139
IL_0039: ldarg.0
1014010140
IL_003a: ldc.i4.m1
1014110141
IL_003b: dup
1014210142
IL_003c: stloc.0
1014310143
IL_003d: stfld "int C.<Produce>d__0.<>1__state"
10144-
IL_0042: br.s IL_00ab
10144+
IL_0042: br.s IL_009f
1014510145
IL_0044: ldarg.0
1014610146
IL_0045: ldloca.s V_1
1014710147
IL_0047: initobj "S"
@@ -10158,7 +10158,7 @@ .locals init (int V_0,
1015810158
IL_0066: dup
1015910159
IL_0067: stloc.0
1016010160
IL_0068: stfld "int C.<Produce>d__0.<>1__state"
10161-
IL_006d: leave IL_01b4
10161+
IL_006d: leave IL_01a8
1016210162
IL_0072: ldarg.0
1016310163
IL_0073: ldc.i4.m1
1016410164
IL_0074: dup
@@ -10167,7 +10167,7 @@ .locals init (int V_0,
1016710167
IL_007b: ldarg.0
1016810168
IL_007c: ldfld "bool C.<Produce>d__0.<>w__disposeMode"
1016910169
IL_0081: brfalse.s IL_0088
10170-
IL_0083: leave IL_018d
10170+
IL_0083: leave IL_0181
1017110171
IL_0088: ldarg.0
1017210172
IL_0089: ldfld "S C.<Produce>d__0.<values2>5__2"
1017310173
IL_008e: box "S"
@@ -10176,121 +10176,118 @@ .locals init (int V_0,
1017610176
IL_0099: ldc.i4.0
1017710177
IL_009a: stfld "bool C.<Produce>d__0.b"
1017810178
IL_009f: ldarg.0
10179-
IL_00a0: ldflda "S C.<Produce>d__0.<values2>5__2"
10180-
IL_00a5: initobj "S"
10181-
IL_00ab: ldarg.0
10182-
IL_00ac: ldfld "bool C.<Produce>d__0.b"
10183-
IL_00b1: brtrue.s IL_0044
10184-
IL_00b3: ldarg.0
10185-
IL_00b4: ldc.i4.2
10186-
IL_00b5: stfld "int C.<Produce>d__0.<>2__current"
10187-
IL_00ba: ldarg.0
10188-
IL_00bb: ldc.i4.s -5
10189-
IL_00bd: dup
10190-
IL_00be: stloc.0
10191-
IL_00bf: stfld "int C.<Produce>d__0.<>1__state"
10192-
IL_00c4: leave IL_01b4
10193-
IL_00c9: ldarg.0
10194-
IL_00ca: ldc.i4.m1
10195-
IL_00cb: dup
10196-
IL_00cc: stloc.0
10197-
IL_00cd: stfld "int C.<Produce>d__0.<>1__state"
10198-
IL_00d2: ldarg.0
10199-
IL_00d3: ldfld "bool C.<Produce>d__0.<>w__disposeMode"
10200-
IL_00d8: brfalse.s IL_00df
10201-
IL_00da: leave IL_018d
10202-
IL_00df: ldarg.0
10203-
IL_00e0: ldfld "System.Threading.Tasks.Task C.<Produce>d__0.task"
10204-
IL_00e5: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()"
10205-
IL_00ea: stloc.2
10206-
IL_00eb: ldloca.s V_2
10207-
IL_00ed: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get"
10208-
IL_00f2: brtrue.s IL_0136
10209-
IL_00f4: ldarg.0
10210-
IL_00f5: ldc.i4.0
10211-
IL_00f6: dup
10212-
IL_00f7: stloc.0
10213-
IL_00f8: stfld "int C.<Produce>d__0.<>1__state"
10214-
IL_00fd: ldarg.0
10215-
IL_00fe: ldloc.2
10216-
IL_00ff: stfld "System.Runtime.CompilerServices.TaskAwaiter C.<Produce>d__0.<>u__1"
10217-
IL_0104: ldarg.0
10218-
IL_0105: stloc.3
10219-
IL_0106: ldarg.0
10220-
IL_0107: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<Produce>d__0.<>t__builder"
10221-
IL_010c: ldloca.s V_2
10222-
IL_010e: ldloca.s V_3
10223-
IL_0110: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter, C.<Produce>d__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.<Produce>d__0)"
10224-
IL_0115: leave IL_01c0
10225-
IL_011a: ldarg.0
10226-
IL_011b: ldfld "System.Runtime.CompilerServices.TaskAwaiter C.<Produce>d__0.<>u__1"
10227-
IL_0120: stloc.2
10179+
IL_00a0: ldfld "bool C.<Produce>d__0.b"
10180+
IL_00a5: brtrue.s IL_0044
10181+
IL_00a7: ldarg.0
10182+
IL_00a8: ldc.i4.2
10183+
IL_00a9: stfld "int C.<Produce>d__0.<>2__current"
10184+
IL_00ae: ldarg.0
10185+
IL_00af: ldc.i4.s -5
10186+
IL_00b1: dup
10187+
IL_00b2: stloc.0
10188+
IL_00b3: stfld "int C.<Produce>d__0.<>1__state"
10189+
IL_00b8: leave IL_01a8
10190+
IL_00bd: ldarg.0
10191+
IL_00be: ldc.i4.m1
10192+
IL_00bf: dup
10193+
IL_00c0: stloc.0
10194+
IL_00c1: stfld "int C.<Produce>d__0.<>1__state"
10195+
IL_00c6: ldarg.0
10196+
IL_00c7: ldfld "bool C.<Produce>d__0.<>w__disposeMode"
10197+
IL_00cc: brfalse.s IL_00d3
10198+
IL_00ce: leave IL_0181
10199+
IL_00d3: ldarg.0
10200+
IL_00d4: ldfld "System.Threading.Tasks.Task C.<Produce>d__0.task"
10201+
IL_00d9: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()"
10202+
IL_00de: stloc.2
10203+
IL_00df: ldloca.s V_2
10204+
IL_00e1: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get"
10205+
IL_00e6: brtrue.s IL_012a
10206+
IL_00e8: ldarg.0
10207+
IL_00e9: ldc.i4.0
10208+
IL_00ea: dup
10209+
IL_00eb: stloc.0
10210+
IL_00ec: stfld "int C.<Produce>d__0.<>1__state"
10211+
IL_00f1: ldarg.0
10212+
IL_00f2: ldloc.2
10213+
IL_00f3: stfld "System.Runtime.CompilerServices.TaskAwaiter C.<Produce>d__0.<>u__1"
10214+
IL_00f8: ldarg.0
10215+
IL_00f9: stloc.3
10216+
IL_00fa: ldarg.0
10217+
IL_00fb: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<Produce>d__0.<>t__builder"
10218+
IL_0100: ldloca.s V_2
10219+
IL_0102: ldloca.s V_3
10220+
IL_0104: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter, C.<Produce>d__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.<Produce>d__0)"
10221+
IL_0109: leave IL_01b4
10222+
IL_010e: ldarg.0
10223+
IL_010f: ldfld "System.Runtime.CompilerServices.TaskAwaiter C.<Produce>d__0.<>u__1"
10224+
IL_0114: stloc.2
10225+
IL_0115: ldarg.0
10226+
IL_0116: ldflda "System.Runtime.CompilerServices.TaskAwaiter C.<Produce>d__0.<>u__1"
10227+
IL_011b: initobj "System.Runtime.CompilerServices.TaskAwaiter"
1022810228
IL_0121: ldarg.0
10229-
IL_0122: ldflda "System.Runtime.CompilerServices.TaskAwaiter C.<Produce>d__0.<>u__1"
10230-
IL_0127: initobj "System.Runtime.CompilerServices.TaskAwaiter"
10231-
IL_012d: ldarg.0
10232-
IL_012e: ldc.i4.m1
10233-
IL_012f: dup
10234-
IL_0130: stloc.0
10235-
IL_0131: stfld "int C.<Produce>d__0.<>1__state"
10236-
IL_0136: ldloca.s V_2
10237-
IL_0138: call "void System.Runtime.CompilerServices.TaskAwaiter.GetResult()"
10238-
IL_013d: ldarg.0
10239-
IL_013e: ldc.i4.3
10240-
IL_013f: stfld "int C.<Produce>d__0.<>2__current"
10229+
IL_0122: ldc.i4.m1
10230+
IL_0123: dup
10231+
IL_0124: stloc.0
10232+
IL_0125: stfld "int C.<Produce>d__0.<>1__state"
10233+
IL_012a: ldloca.s V_2
10234+
IL_012c: call "void System.Runtime.CompilerServices.TaskAwaiter.GetResult()"
10235+
IL_0131: ldarg.0
10236+
IL_0132: ldc.i4.3
10237+
IL_0133: stfld "int C.<Produce>d__0.<>2__current"
10238+
IL_0138: ldarg.0
10239+
IL_0139: ldc.i4.s -6
10240+
IL_013b: dup
10241+
IL_013c: stloc.0
10242+
IL_013d: stfld "int C.<Produce>d__0.<>1__state"
10243+
IL_0142: leave.s IL_01a8
1024110244
IL_0144: ldarg.0
10242-
IL_0145: ldc.i4.s -6
10243-
IL_0147: dup
10244-
IL_0148: stloc.0
10245-
IL_0149: stfld "int C.<Produce>d__0.<>1__state"
10246-
IL_014e: leave.s IL_01b4
10247-
IL_0150: ldarg.0
10248-
IL_0151: ldc.i4.m1
10249-
IL_0152: dup
10250-
IL_0153: stloc.0
10251-
IL_0154: stfld "int C.<Produce>d__0.<>1__state"
10252-
IL_0159: ldarg.0
10253-
IL_015a: ldfld "bool C.<Produce>d__0.<>w__disposeMode"
10254-
IL_015f: pop
10255-
IL_0160: leave.s IL_018d
10245+
IL_0145: ldc.i4.m1
10246+
IL_0146: dup
10247+
IL_0147: stloc.0
10248+
IL_0148: stfld "int C.<Produce>d__0.<>1__state"
10249+
IL_014d: ldarg.0
10250+
IL_014e: ldfld "bool C.<Produce>d__0.<>w__disposeMode"
10251+
IL_0153: pop
10252+
IL_0154: leave.s IL_0181
1025610253
}
1025710254
catch System.Exception
1025810255
{
10259-
IL_0162: stloc.s V_4
10260-
IL_0164: ldarg.0
10261-
IL_0165: ldc.i4.s -2
10262-
IL_0167: stfld "int C.<Produce>d__0.<>1__state"
10263-
IL_016c: ldarg.0
10264-
IL_016d: ldc.i4.0
10265-
IL_016e: stfld "int C.<Produce>d__0.<>2__current"
10266-
IL_0173: ldarg.0
10267-
IL_0174: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<Produce>d__0.<>t__builder"
10268-
IL_0179: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()"
10269-
IL_017e: ldarg.0
10270-
IL_017f: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<Produce>d__0.<>v__promiseOfValueOrEnd"
10271-
IL_0184: ldloc.s V_4
10272-
IL_0186: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetException(System.Exception)"
10273-
IL_018b: leave.s IL_01c0
10256+
IL_0156: stloc.s V_4
10257+
IL_0158: ldarg.0
10258+
IL_0159: ldc.i4.s -2
10259+
IL_015b: stfld "int C.<Produce>d__0.<>1__state"
10260+
IL_0160: ldarg.0
10261+
IL_0161: ldc.i4.0
10262+
IL_0162: stfld "int C.<Produce>d__0.<>2__current"
10263+
IL_0167: ldarg.0
10264+
IL_0168: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<Produce>d__0.<>t__builder"
10265+
IL_016d: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()"
10266+
IL_0172: ldarg.0
10267+
IL_0173: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<Produce>d__0.<>v__promiseOfValueOrEnd"
10268+
IL_0178: ldloc.s V_4
10269+
IL_017a: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetException(System.Exception)"
10270+
IL_017f: leave.s IL_01b4
1027410271
}
10275-
IL_018d: ldarg.0
10276-
IL_018e: ldc.i4.s -2
10277-
IL_0190: stfld "int C.<Produce>d__0.<>1__state"
10278-
IL_0195: ldarg.0
10279-
IL_0196: ldc.i4.0
10280-
IL_0197: stfld "int C.<Produce>d__0.<>2__current"
10281-
IL_019c: ldarg.0
10282-
IL_019d: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<Produce>d__0.<>t__builder"
10283-
IL_01a2: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()"
10284-
IL_01a7: ldarg.0
10285-
IL_01a8: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<Produce>d__0.<>v__promiseOfValueOrEnd"
10286-
IL_01ad: ldc.i4.0
10287-
IL_01ae: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetResult(bool)"
10288-
IL_01b3: ret
10289-
IL_01b4: ldarg.0
10290-
IL_01b5: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<Produce>d__0.<>v__promiseOfValueOrEnd"
10291-
IL_01ba: ldc.i4.1
10292-
IL_01bb: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetResult(bool)"
10293-
IL_01c0: ret
10272+
IL_0181: ldarg.0
10273+
IL_0182: ldc.i4.s -2
10274+
IL_0184: stfld "int C.<Produce>d__0.<>1__state"
10275+
IL_0189: ldarg.0
10276+
IL_018a: ldc.i4.0
10277+
IL_018b: stfld "int C.<Produce>d__0.<>2__current"
10278+
IL_0190: ldarg.0
10279+
IL_0191: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<Produce>d__0.<>t__builder"
10280+
IL_0196: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()"
10281+
IL_019b: ldarg.0
10282+
IL_019c: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<Produce>d__0.<>v__promiseOfValueOrEnd"
10283+
IL_01a1: ldc.i4.0
10284+
IL_01a2: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetResult(bool)"
10285+
IL_01a7: ret
10286+
IL_01a8: ldarg.0
10287+
IL_01a9: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<Produce>d__0.<>v__promiseOfValueOrEnd"
10288+
IL_01ae: ldc.i4.1
10289+
IL_01af: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetResult(bool)"
10290+
IL_01b4: ret
1029410291
}
1029510292
""");
1029610293
}

0 commit comments

Comments
 (0)