Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code - #127511

Merged
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher
May 4, 2026
Merged

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code#127511
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 28, 2026

Copy link
Copy Markdown
Member

Remove RestoreExecutionContext call from JIT resumption code and from the interpreter. Instead encode the ExecutionContext's location in the continuation and let the dispatcher restore it. This removes a TLS access + helper call from the resumption path (avoiding the TLS and inlining the helper call in the dispatcher).

Improves suspension/resumption performance by about 7-8% and is also a good size improvement. Removing the call from the resumption path allows keeping the continuation in a volatile register, which also helps register allocation in a number of cases.

Diffs before JIT-EE GUID update

Micro benchmark with warmup
usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceAsyncMicro;publicclassProgram{staticvoidMain(){NullAwaiterna=newNullAwaiter();for(inti=0;i<10;i++){for(intj=0;j<100;j++){Taskt=Foo(100,na);while(!t.IsCompleted){na.Continue();}}Thread.Sleep(100);}for(inti=0;i<50;i++){Taskt=Foo(10_000_000,na);while(!t.IsCompleted){na.Continue();}}}staticints_value;staticasyncTaskFoo(intn,NullAwaiterna){for(inti=0;i<n;i++){s_value+=i;}Stopwatchtimer=Stopwatch.StartNew();for(inti=0;i<n;i++){awaitna;}if(n>100)Console.WriteLine("Took {0:F1} ms",timer.Elapsed.TotalMilliseconds);}privateclassNullAwaiter:ICriticalNotifyCompletion{publicActionContinue;publicNullAwaiterGetAwaiter()=>this;publicboolIsCompleted=>false;publicvoidGetResult(){}publicvoidUnsafeOnCompleted(Actioncontinuation){Continue=continuation;}publicvoidOnCompleted(Actioncontinuation){thrownewNotImplementedException();}}}

About 7-8% improvement:

-Took 268.5 ms-Took 265.9 ms-Took 267.9 ms-Took 270.0 ms-Took 269.4 ms+Took 249.4 ms+Took 248.3 ms+Took 250.3 ms+Took 249.2 ms+Took 248.9 ms
NativeAOT test sizes
BaseSizeDiffSizeDeltaPercentName
31,037,44030,944,256-93,184-0.300%System.Net.Http.Functional.Tests.exe
16,847,87216,803,328-44,544-0.264%System.Linq.AsyncEnumerable.Tests.exe
115,269,120115,089,408-179,712-0.156%System.Text.Json.SourceGeneration.Roslyn4.4.Tests.exe
20,942,33620,912,640-29,696-0.142%System.Net.Quic.Functional.Tests.exe
20,033,02420,005,376-27,648-0.138%System.Formats.Tar.Tests.exe
19,558,91219,533,824-25,088-0.128%System.IO.Compression.Tests.exe
10,055,16810,042,880-12,288-0.122%System.IO.Compression.ZipFile.Tests.exe
14,901,76014,883,840-17,920-0.120%System.Xml.Linq.Streaming.Tests.exe
16,778,75216,758,784-19,968-0.119%System.Xml.Linq.Misc.Tests.exe
28,789,76028,757,504-32,256-0.112%System.Net.Http.WinHttpHandler.Functional.Tests.exe
16,516,60816,498,176-18,432-0.112%System.Xml.Linq.Events.Tests.exe
17,065,47217,046,528-18,944-0.111%System.Xml.Linq.xNodeBuilder.Tests.exe
22,732,80022,708,224-24,576-0.108%System.Net.Sockets.Tests.exe
16,671,74416,653,824-17,920-0.107%System.Xml.Linq.Properties.Tests.exe
17,123,84017,105,920-17,920-0.105%System.Xml.Linq.TreeManipulation.Tests.exe
17,007,61616,989,696-17,920-0.105%System.Xml.Linq.xNodeReader.Tests.exe
20,003,84019,982,848-20,992-0.105%System.Net.WebSockets.Client.Tests.exe
19,053,05619,034,112-18,944-0.099%System.Net.HttpListener.Tests.exe
10,660,86410,650,624-10,240-0.096%System.IO.Pipelines.Tests.exe
20,267,00820,248,064-18,944-0.093%System.Threading.Tasks.Dataflow.Tests.exe
17,728,51217,713,664-14,848-0.084%System.Threading.Tasks.Extensions.Tests.exe
14,569,47214,557,696-11,776-0.081%System.Net.WebClient.Tests.exe
11,992,06411,982,336-9,728-0.081%System.IO.Tests.exe
21,089,79221,072,896-16,896-0.080%System.Net.Requests.Tests.exe
21,708,80021,691,392-17,408-0.080%System.IO.FileSystem.Tests.exe
10,278,91210,270,720-8,192-0.080%System.Threading.Channels.Tests.exe
27,894,27227,874,304-19,968-0.072%System.Net.Security.Tests.exe
18,447,87218,434,560-13,312-0.072%System.Threading.Tasks.Parallel.Tests.exe
13,242,36813,233,152-9,216-0.070%System.IO.Packaging.Tests.exe
9,731,0729,724,416-6,656-0.068%System.Threading.RateLimiting.Tests.exe
33,165,31233,142,784-22,528-0.068%System.Private.Xml.Tests.exe
13,869,05613,859,840-9,216-0.066%Microsoft.Extensions.Configuration.Functional.Tests.exe
19,545,60019,532,800-12,800-0.065%System.Diagnostics.Process.Tests.exe
12,849,66412,841,472-8,192-0.064%System.Xml.Schema.Extensions.Tests.exe
12,416,00012,408,320-7,680-0.062%System.Xml.Linq.SDMSample.Tests.exe
17,431,55217,420,800-10,752-0.062%System.Net.Ping.Functional.Tests.exe
20,540,41620,527,616-12,800-0.062%System.Threading.Tasks.Tests.exe
15,759,87215,750,144-9,728-0.062%System.Windows.Extensions.Tests.exe
10,056,19210,050,048-6,144-0.061%System.Net.ServerSentEvents.Tests.exe
15,102,46415,093,248-9,216-0.061%System.Drawing.Primitives.Tests.exe
17,571,84017,561,088-10,752-0.061%MetricOuterLoop1.Tests.exe
17,566,72017,555,968-10,752-0.061%MetricOuterLoop.Tests.exe
19,289,60019,277,824-11,776-0.061%System.IO.Pipes.Tests.exe
17,791,48817,780,736-10,752-0.060%System.Formats.Tar.Manual.Tests.exe
17,967,61617,956,864-10,752-0.060%System.Threading.ThreadPool.WindowsThreadPool.Tests.exe
17,329,15217,318,912-10,240-0.059%System.Threading.Timer.Tests.exe
14,130,17614,121,984-8,192-0.058%System.DirectoryServices.Protocols.Tests.exe
17,616,89617,606,656-10,240-0.058%System.Threading.Thread.Tests.exe
19,681,79219,670,528-11,264-0.057%System.Net.Http.Unit.Tests.exe
17,160,19217,150,464-9,728-0.057%System.Runtime.Serialization.Formatters.Disabled.Tests.exe
17,967,10417,956,864-10,240-0.057%System.Threading.ThreadPool.Tests.exe
19,870,72019,859,456-11,264-0.057%System.Text.Encoding.Tests.exe
18,774,01618,763,264-10,752-0.057%Microsoft.Extensions.FileProviders.Physical.Tests.exe
27,160,06427,144,704-15,360-0.057%Microsoft.Extensions.Hosting.Unit.Tests.exe
17,214,97617,205,248-9,728-0.057%System.Net.ServicePoint.Tests.exe
17,312,76817,303,040-9,728-0.056%System.Security.Principal.Windows.Tests.exe
17,230,84817,221,120-9,728-0.056%System.ComponentModel.EventBasedAsync.Tests.exe
18,128,89618,118,656-10,240-0.056%System.Diagnostics.TextWriterTraceListener.Tests.exe
17,298,94417,289,216-9,728-0.056%System.Security.Claims.Tests.exe
17,431,04017,421,312-9,728-0.056%System.Diagnostics.TraceSource.Tests.exe
17,282,04817,272,320-9,728-0.056%System.Threading.Overlapped.Tests.exe
18,177,53618,167,296-10,240-0.056%System.Text.Encoding.CodePages.Tests.exe
17,356,28817,346,560-9,728-0.056%Microsoft.Win32.SystemEvents.Tests.exe
18,586,62418,576,384-10,240-0.055%ComInterfaceGenerator.Tests.exe
17,661,44017,651,712-9,728-0.055%System.IO.FileSystem.Watcher.Tests.exe
9,251,8409,246,720-5,120-0.055%Microsoft.Bcl.AsyncInterfaces.Tests.exe
13,941,24813,933,568-7,680-0.055%Microsoft.Extensions.Configuration.Xml.Tests.exe
18,492,92818,482,688-10,240-0.055%Microsoft.Extensions.Configuration.Tests.exe
17,662,97617,653,248-9,728-0.055%System.Buffers.Tests.exe
18,489,34418,479,104-10,240-0.055%Microsoft.Extensions.Hosting.Systemd.Tests.exe
15,080,44815,072,256-8,192-0.054%System.Security.Cryptography.Cng.Tests.exe
17,154,04817,144,832-9,216-0.054%IcuAppLocal.Tests.exe
15,039,48815,031,296-8,192-0.054%System.Data.DataSetExtensions.Tests.exe
18,062,33618,052,608-9,728-0.054%System.Console.Tests.exe
17,288,19217,278,976-9,216-0.053%System.Runtime.InteropServices.RuntimeInformation.Tests.exe
17,361,40817,352,192-9,216-0.053%System.Diagnostics.StackTrace.Tests.exe
18,455,55218,445,824-9,728-0.053%Microsoft.Extensions.Configuration.FileExtensions.Tests.exe
17,235,96817,226,752-9,216-0.053%System.Runtime.InvariantTimezone.Tests.exe
18,518,01618,508,288-9,728-0.053%System.IO.MemoryMappedFiles.Tests.exe
18,693,63218,683,904-9,728-0.052%Microsoft.Extensions.Logging.Console.Tests.exe
18,032,12818,022,912-9,216-0.051%Microsoft.Extensions.Diagnostics.Tests.exe
16,107,00816,098,816-8,192-0.051%System.Data.Odbc.Tests.exe
24,284,67224,272,384-12,288-0.051%Microsoft.Extensions.Http.Tests.exe
20,532,73620,522,496-10,240-0.050%System.Runtime.Extensions.Tests.exe
18,371,58418,362,368-9,216-0.050%System.Threading.Tests.exe
18,356,73618,347,520-9,216-0.050%Microsoft.Extensions.FileProviders.Composite.Tests.exe
18,381,82418,372,608-9,216-0.050%Microsoft.Extensions.Primitives.Tests.exe
11,331,07211,325,440-5,632-0.050%System.Net.WebSockets.Tests.exe
19,295,74419,286,016-9,728-0.050%System.Net.Primitives.Functional.Tests.exe
19,972,60819,962,880-9,728-0.049%Microsoft.Extensions.Logging.Tests.exe
11,588,09611,582,464-5,632-0.049%System.Net.Http.Json.Unit.Tests.exe
19,744,76819,735,040-9,728-0.049%System.Resources.ResourceManager.Tests.exe
9,334,7849,330,176-4,608-0.049%Microsoft.Extensions.Diagnostics.Abstractions.Tests.exe
18,833,92018,824,704-9,216-0.049%System.Runtime.Caching.Tests.exe
19,080,19219,070,976-9,216-0.048%Microsoft.Extensions.Hosting.WindowsServices.Tests.exe
9,660,4169,655,808-4,608-0.048%Microsoft.Extensions.Hosting.Functional.Tests.exe
20,475,90420,466,176-9,728-0.048%System.Diagnostics.DiagnosticSource.Tests.exe
20,741,63220,731,904-9,728-0.047%System.Collections.Concurrent.Tests.exe
10,106,36810,101,760-4,608-0.046%Microsoft.Extensions.Caching.Memory.Tests.exe
20,234,75220,225,536-9,216-0.046%System.Runtime.InteropServices.Tests.exe
20,454,91220,445,696-9,216-0.045%System.Reflection.Tests.exe
19,486,20819,477,504-8,704-0.045%Microsoft.Extensions.Configuration.UserSecrets.Tests.exe
11,274,24011,269,120-5,120-0.045%System.IO.Compression.Brotli.Tests.exe
19,555,84019,547,136-8,704-0.045%Microsoft.Extensions.Configuration.Json.Tests.exe
23,405,05623,394,816-10,240-0.044%System.Memory.Tests.exe
25,891,32825,880,064-11,264-0.044%System.Text.Json.SourceGeneration.Roslyn3.11.Tests.exe
10,510,33610,505,728-4,608-0.044%Microsoft.Extensions.Options.Tests.exe
9,442,8169,438,720-4,096-0.043%Microsoft.Extensions.Logging.Testing.Tests.exe
26,440,70426,429,440-11,264-0.043%System.ComponentModel.TypeConverter.Tests.exe
21,622,78421,613,568-9,216-0.043%System.Data.OleDb.Tests.exe
26,006,52825,996,288-10,240-0.039%System.Globalization.Nls.Tests.exe
20,808,70420,801,024-7,680-0.037%System.Security.Cryptography.Csp.Tests.exe
29,403,13629,392,384-10,752-0.037%Microsoft.Extensions.DependencyModel.Tests.exe
26,095,61626,085,888-9,728-0.037%System.Globalization.Tests.exe
21,072,38421,064,704-7,680-0.036%Microsoft.Extensions.Logging.EventSource.Tests.exe
45,486,08045,470,208-15,872-0.035%System.Security.Cryptography.Tests.exe
32,739,84032,730,112-9,728-0.030%System.Linq.Expressions.Tests.exe
33,385,98433,376,256-9,728-0.029%Microsoft.Bcl.Cryptography.Tests.exe
44,704,76844,693,504-11,264-0.025%System.Runtime.Tests.exe
2,233,3442,232,832-512-0.023%clrjit.dll
10,494,46410,492,928-1,536-0.015%System.Net.Http.WinHttpHandler.Unit.Tests.exe
10,586,11210,584,576-1,536-0.015%Common.Tests.exe
9,026,0489,025,024-1,024-0.011%Microsoft.Extensions.FileSystemGlobbing.Tests.exe
9,347,5849,346,560-1,024-0.011%System.Security.Permissions.Tests.exe
9,612,8009,611,776-1,024-0.011%System.Diagnostics.EventLog.Tests.exe
12,185,08812,184,064-1,024-0.008%System.Net.NetworkInformation.Functional.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Nls.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Tests.exe
8,743,9368,743,424-512-0.006%Invariant.Tests.exe
8,975,8728,975,360-512-0.006%System.Net.Primitives.Pal.Tests.exe
8,798,2088,797,696-512-0.006%System.Resources.Reader.Tests.exe
8,667,1368,666,624-512-0.006%System.Runtime.CompilerServices.Unsafe.Tests.exe
8,916,4808,915,968-512-0.006%System.IO.Pipes.AccessControl.Tests.exe
9,027,0729,026,560-512-0.006%System.Net.NameResolution.Pal.Tests.exe
9,191,9369,191,424-512-0.006%Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.exe
8,763,9048,763,392-512-0.006%Microsoft.Bcl.TimeProvider.Tests.exe
8,609,7928,609,280-512-0.006%System.Composition.Runtime.Tests.exe
9,129,4729,128,960-512-0.006%System.Security.AccessControl.Tests.exe
8,803,3288,802,816-512-0.006%System.Web.HttpUtility.Tests.exe
9,041,9209,041,408-512-0.006%Microsoft.Extensions.Configuration.CommandLine.Tests.exe
8,638,4648,637,952-512-0.006%System.Globalization.CalendarsWithConfigSwitch.Tests.exe
8,533,5048,532,992-512-0.006%System.ComponentModel.Tests.exe
8,686,5928,686,080-512-0.006%System.Security.Cryptography.ProtectedData.Tests.exe
8,755,7128,755,200-512-0.006%System.IO.FileSystem.DriveInfo.Tests.exe
8,977,4088,976,896-512-0.006%Microsoft.Win32.Registry.Tests.exe
8,685,5688,685,056-512-0.006%System.IO.FileSystem.Manual.Tests.exe
9,095,6809,095,168-512-0.006%System.IO.FileSystem.AccessControl.Tests.exe
10,048,51210,048,000-512-0.005%System.Diagnostics.Debug.Tests.exe
11,179,52011,179,008-512-0.005%System.Text.Encodings.Web.Tests.exe
11,034,11211,033,600-512-0.005%System.Runtime.Numerics.Tests.exe
11,363,32811,362,816-512-0.005%System.Net.Security.Unit.Tests.exe
9,337,3449,336,832-512-0.005%System.IO.IsolatedStorage.Tests.exe
9,748,9929,749,504+512+0.005%System.Formats.Asn1.Tests.exe
9,473,5369,473,024-512-0.005%Microsoft.Extensions.Configuration.Ini.Tests.exe
10,936,32010,935,808-512-0.005%System.Runtime.Intrinsics.Tests.exe
9,571,3289,570,816-512-0.005%System.Memory.Data.Tests.exe
9,660,9289,660,416-512-0.005%System.IO.UnmanagedMemoryStream.Tests.exe
9,524,7369,524,224-512-0.005%System.IO.Hashing.Tests.exe
9,361,9209,361,408-512-0.005%System.Net.Mail.Unit.Tests.exe
11,590,14411,589,632-512-0.004%System.Resources.Extensions.Tests.exe
11,469,31211,468,800-512-0.004%System.IO.Ports.Tests.exe
11,779,07211,778,560-512-0.004%System.Security.Cryptography.Cose.Tests.exe
17,824,76817,824,256-512-0.003%System.Collections.Tests.exe
18,770,43218,770,944+512+0.003%System.Numerics.Vectors.Tests.exe
22,320,64022,320,128-512-0.002%System.Security.Cryptography.Pkcs.Tests.exe
8,988,6728,988,67200.000%System.Runtime.Serialization.Primitives.Tests.exe
8,690,1768,690,17600.000%System.Security.SecureString.Tests.exe
9,201,6649,201,66400.000%System.ServiceProcess.ServiceController.Tests.exe
7,318,0167,318,01600.000%XUnitLogChecker.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
84,48084,48000.000%System.Globalization.Native.dll
108,032108,03200.000%CMakeCXXCompilerId.exe
108,032108,03200.000%CMakeCCompilerId.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
8,673,2808,673,28000.000%System.Runtime.InteropServices.ComDisabled.Tests.exe
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,608,7688,608,76800.000%System.Xml.Linq.Axes.Tests.exe
9,069,0569,069,05600.000%System.ValueTuple.Tests.exe
8,945,1528,945,15200.000%System.Threading.AccessControl.Tests.exe
9,690,1129,690,11200.000%System.Text.RegularExpressions.Unit.Tests.exe
8,543,2328,543,23200.000%System.Text.Encoding.Extensions.Tests.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
536,096536,09600.000%msquic.dll
8,529,4088,529,40800.000%System.IO.FileSystem.Primitives.Tests.exe
8,532,4808,532,48000.000%System.Runtime.CompilerServices.VisualC.Tests.exe
536,096536,09600.000%msquic.dll
1,308,6721,308,67200.000%mscordbi.dll
1,501,6961,501,69600.000%mscordaccore.dll
1,501,6961,501,69600.000%mscordaccore_amd64_amd64_42.42.42.42424.dll
361,984361,98400.000%hostpolicy.dll
350,208350,20800.000%hostfxr.dll
62,46462,46400.000%createdump.exe
210,944210,94400.000%corerun.exe
4,955,6484,955,64800.000%coreclr.dll
722,944722,94400.000%clrgcexp.dll
678,400678,40000.000%clrgc.dll
307,200307,20000.000%clretwrc.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
84,48084,48000.000%System.Globalization.Native.dll
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
696,320696,32000.000%FileCheck.exe
9,956,3529,956,35200.000%llvm-mca.exe
13,419,52013,419,52000.000%crossgen2.exe
7,703,0407,703,04000.000%ilasm.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
15,940,09615,940,09600.000%ilc.exe
8,938,4968,938,49600.000%Microsoft.Bcl.Memory.Tests.exe
8,578,0488,578,04800.000%Microsoft.Bcl.Numerics.Tests.exe
8,587,2648,587,26400.000%Microsoft.Extensions.Hosting.Abstractions.Tests.exe
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
9,947,6489,947,64800.000%LibraryImportGenerator.Tests.exe
8,655,8728,655,87200.000%System.Runtime.Handles.Tests.exe
16,973,82416,973,82400.000%System.Private.CoreLib.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
8,591,3608,591,36000.000%System.Resources.Writer.Tests.exe
9,011,2009,011,20000.000%System.Reflection.TypeExtensions.Tests.exe
12,271,10412,271,10400.000%System.Reflection.Metadata.Tests.exe
8,849,9208,849,92000.000%System.Reflection.Extensions.Tests.exe
9,350,6569,350,65600.000%System.Reflection.Context.Tests.exe
8,704,5128,704,51200.000%System.Private.Uri.Unit.Tests.exe
9,631,7449,631,74400.000%System.Private.Uri.Functional.Tests.exe
9,785,8569,785,85600.000%System.Net.WebProxy.Tests.exe
8,627,2008,627,20000.000%System.Net.WebHeaderCollection.Tests.exe
9,300,9929,300,99200.000%System.Net.Primitives.UnitTests.Tests.exe
15,486,97615,486,97600.000%System.Linq.Tests.exe
696,320696,32000.000%FileCheck.exe
9,150,9769,150,97600.000%System.Globalization.Calendars.Tests.exe
9,837,5689,837,56800.000%System.Formats.Nrbf.Tests.exe
8,534,5288,534,52800.000%System.Diagnostics.Tools.Tests.exe
8,702,4648,702,46400.000%System.Diagnostics.FileVersionInfo.Tests.exe
8,547,8408,547,84000.000%System.Diagnostics.Contracts.Tests.exe
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,649,2168,649,21600.000%Microsoft.Win32.Primitives.Tests.exe
9,934,3369,934,33600.000%System.Collections.NonGeneric.Tests.exe
9,734,6569,734,65600.000%System.Collections.Specialized.Tests.exe
9,147,3929,147,39200.000%System.ComponentModel.Primitives.Tests.exe
8,544,7688,544,76800.000%System.Composition.AttributeModel.Tests.exe
9,615,8729,615,87200.000%System.Composition.Convention.Tests.exe
8,821,7608,821,76000.000%System.Console.Manual.Tests.exe
8,632,8328,632,83200.000%Microsoft.Win32.Registry.AccessControl.Tests.exe
9,956,3529,956,35200.000%llvm-mca.exe

Remove `RestoreExecutionContext` call from JIT resumption code and from
the interpreter. Instead encode the `ExecutionContext`'s location in the
continuation and let the dispatcher restore it. This removes a TLS
access + helper call from the resumption path (avoiding the TLS and
inlining the helper call in the dispatcher).
Improves suspension/resumption performance by about 5-6% and should also
be a small size improvement.
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes CoreCLR runtime-async suspension/resumption so the dispatcher (managed AsyncHelpers) restores ExecutionContext, instead of having interpreter/JIT resumption stubs call a restore helper. The continuation’s flags now encode the ExecutionContext storage slot, enabling the dispatcher to restore without an extra TLS lookup + helper call on the hot resumption path.

Changes:

  • Add continuation support for locating/storing the ExecutionContext via encoded indices in continuation flags (VM + managed + JIT + interpreter).
  • Remove RestoreExecutionContext calls from interpreter and JIT resumption code; add restoration to the dispatcher loop.
  • Preserve BBF_ASYNC_RESUMPTION across certain flow optimizations that may bypass resumption stubs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/vm/object.hAdds VM helper to locate ExecutionContext storage in a continuation via encoded flag bits.
src/coreclr/vm/interpexec.cppWrites captured ExecutionContext via the encoded slot; removes interpreter-side restore on resume.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.csMoves ExecutionContext restore into dispatcher; adjusts flag layout and RestoreExecutionContext signature to avoid TLS lookup.
src/coreclr/jit/fgopt.cppCopies BBF_ASYNC_RESUMPTION during certain jump/switch/flow optimizations to preserve async side-entry affordances.
src/coreclr/jit/async.cppUpdates continuation layout/flag encoding for ExecutionContext; removes JIT-side restore on resumption.
src/coreclr/interpreter/inc/interpretershared.hRemoves interpreter suspend-data field that stored a raw execution-context offset.
src/coreclr/interpreter/compiler.cppEncodes ExecutionContext slot in flags and updates interpreter continuation layout accordingly.
src/coreclr/inc/corinfo.hUpdates CorInfoContinuationFlags bit assignments to include ExecutionContext index encoding.
Comments suppressed due to low confidence (2)

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:554

  • RuntimeAsyncStackState contains managed reference fields, but this local is left uninitialized before its address is stored in TLS (awaitState.Push(&stackState)). This can expose garbage references to the GC (and Push only initializes a subset of fields), risking GC crashes/corruption. Initialize stackState to default (or otherwise fully clear all reference fields before any GC safepoint) before calling Push.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:655

  • Same issue as in DispatchContinuations: RuntimeAsyncStackState stackState; is uninitialized even though the struct contains managed references and its address is pushed into TLS via awaitState.Push(&stackState). This can leave garbage object references visible to the GC until fields are explicitly set. Ensure stackState is zero-initialized (e.g., = default) or otherwise cleared before pushing.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

CopilotAI review requested due to automatic review settings April 29, 2026 09:11

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • InterpAsyncSuspendData.restoreExecutionContextMethod is still populated, but after removing the interpreter-side RestoreExecutionContext call there don’t appear to be any remaining reads of this field. Consider removing the field from InterpAsyncSuspendData (and this assignment) to reduce per-suspension metadata size and avoid dead state.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

CopilotAI review requested due to automatic review settings April 30, 2026 11:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • CORINFO_ASYNC_INFO no longer exposes restoreExecutionContextMethHnd, but the interpreter still stores asyncInfo.restoreExecutionContextMethHnd into InterpAsyncSuspendData. This will fail to compile and should be removed/rewired now that execution context restoration is done by the dispatcher.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

Comment threadsrc/coreclr/inc/corinfo.h
Comment threadsrc/coreclr/vm/corelib.h
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Comment threadsrc/coreclr/interpreter/inc/interpretershared.h
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Comment threadsrc/coreclr/jit/async.cpp
Comment threadsrc/coreclr/jit/fgbasic.cpp
CopilotAI review requested due to automatic review settings April 30, 2026 12:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 30, 2026 12:38

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/interpexec.cpp

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @VSadov (async) @AndyAyersMS (JIT) @davidwrighton /@janvorli (interpreter)

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT changes look good.

Comment threadsrc/coreclr/jit/fgbasic.cpp

@VSadovVSadov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Will merge this, @janvorli@davidwrighton let me know if you have any comments on the interpreter change and I can address it in a follow-up.

@jakobbotsch
jakobbotsch merged commit 83ebc00 into dotnet:mainMay 4, 2026
124 checks passed
@jakobbotsch
jakobbotsch deleted the restore-execution-context-in-dispatcher branch May 4, 2026 11:06
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@VSadov@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code - #127511

Merged
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher
May 4, 2026
Merged

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code#127511
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 28, 2026

Copy link
Copy Markdown
Member

Remove RestoreExecutionContext call from JIT resumption code and from the interpreter. Instead encode the ExecutionContext's location in the continuation and let the dispatcher restore it. This removes a TLS access + helper call from the resumption path (avoiding the TLS and inlining the helper call in the dispatcher).

Improves suspension/resumption performance by about 7-8% and is also a good size improvement. Removing the call from the resumption path allows keeping the continuation in a volatile register, which also helps register allocation in a number of cases.

Diffs before JIT-EE GUID update

Micro benchmark with warmup
usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceAsyncMicro;publicclassProgram{staticvoidMain(){NullAwaiterna=newNullAwaiter();for(inti=0;i<10;i++){for(intj=0;j<100;j++){Taskt=Foo(100,na);while(!t.IsCompleted){na.Continue();}}Thread.Sleep(100);}for(inti=0;i<50;i++){Taskt=Foo(10_000_000,na);while(!t.IsCompleted){na.Continue();}}}staticints_value;staticasyncTaskFoo(intn,NullAwaiterna){for(inti=0;i<n;i++){s_value+=i;}Stopwatchtimer=Stopwatch.StartNew();for(inti=0;i<n;i++){awaitna;}if(n>100)Console.WriteLine("Took {0:F1} ms",timer.Elapsed.TotalMilliseconds);}privateclassNullAwaiter:ICriticalNotifyCompletion{publicActionContinue;publicNullAwaiterGetAwaiter()=>this;publicboolIsCompleted=>false;publicvoidGetResult(){}publicvoidUnsafeOnCompleted(Actioncontinuation){Continue=continuation;}publicvoidOnCompleted(Actioncontinuation){thrownewNotImplementedException();}}}

About 7-8% improvement:

-Took 268.5 ms-Took 265.9 ms-Took 267.9 ms-Took 270.0 ms-Took 269.4 ms+Took 249.4 ms+Took 248.3 ms+Took 250.3 ms+Took 249.2 ms+Took 248.9 ms
NativeAOT test sizes
BaseSizeDiffSizeDeltaPercentName
31,037,44030,944,256-93,184-0.300%System.Net.Http.Functional.Tests.exe
16,847,87216,803,328-44,544-0.264%System.Linq.AsyncEnumerable.Tests.exe
115,269,120115,089,408-179,712-0.156%System.Text.Json.SourceGeneration.Roslyn4.4.Tests.exe
20,942,33620,912,640-29,696-0.142%System.Net.Quic.Functional.Tests.exe
20,033,02420,005,376-27,648-0.138%System.Formats.Tar.Tests.exe
19,558,91219,533,824-25,088-0.128%System.IO.Compression.Tests.exe
10,055,16810,042,880-12,288-0.122%System.IO.Compression.ZipFile.Tests.exe
14,901,76014,883,840-17,920-0.120%System.Xml.Linq.Streaming.Tests.exe
16,778,75216,758,784-19,968-0.119%System.Xml.Linq.Misc.Tests.exe
28,789,76028,757,504-32,256-0.112%System.Net.Http.WinHttpHandler.Functional.Tests.exe
16,516,60816,498,176-18,432-0.112%System.Xml.Linq.Events.Tests.exe
17,065,47217,046,528-18,944-0.111%System.Xml.Linq.xNodeBuilder.Tests.exe
22,732,80022,708,224-24,576-0.108%System.Net.Sockets.Tests.exe
16,671,74416,653,824-17,920-0.107%System.Xml.Linq.Properties.Tests.exe
17,123,84017,105,920-17,920-0.105%System.Xml.Linq.TreeManipulation.Tests.exe
17,007,61616,989,696-17,920-0.105%System.Xml.Linq.xNodeReader.Tests.exe
20,003,84019,982,848-20,992-0.105%System.Net.WebSockets.Client.Tests.exe
19,053,05619,034,112-18,944-0.099%System.Net.HttpListener.Tests.exe
10,660,86410,650,624-10,240-0.096%System.IO.Pipelines.Tests.exe
20,267,00820,248,064-18,944-0.093%System.Threading.Tasks.Dataflow.Tests.exe
17,728,51217,713,664-14,848-0.084%System.Threading.Tasks.Extensions.Tests.exe
14,569,47214,557,696-11,776-0.081%System.Net.WebClient.Tests.exe
11,992,06411,982,336-9,728-0.081%System.IO.Tests.exe
21,089,79221,072,896-16,896-0.080%System.Net.Requests.Tests.exe
21,708,80021,691,392-17,408-0.080%System.IO.FileSystem.Tests.exe
10,278,91210,270,720-8,192-0.080%System.Threading.Channels.Tests.exe
27,894,27227,874,304-19,968-0.072%System.Net.Security.Tests.exe
18,447,87218,434,560-13,312-0.072%System.Threading.Tasks.Parallel.Tests.exe
13,242,36813,233,152-9,216-0.070%System.IO.Packaging.Tests.exe
9,731,0729,724,416-6,656-0.068%System.Threading.RateLimiting.Tests.exe
33,165,31233,142,784-22,528-0.068%System.Private.Xml.Tests.exe
13,869,05613,859,840-9,216-0.066%Microsoft.Extensions.Configuration.Functional.Tests.exe
19,545,60019,532,800-12,800-0.065%System.Diagnostics.Process.Tests.exe
12,849,66412,841,472-8,192-0.064%System.Xml.Schema.Extensions.Tests.exe
12,416,00012,408,320-7,680-0.062%System.Xml.Linq.SDMSample.Tests.exe
17,431,55217,420,800-10,752-0.062%System.Net.Ping.Functional.Tests.exe
20,540,41620,527,616-12,800-0.062%System.Threading.Tasks.Tests.exe
15,759,87215,750,144-9,728-0.062%System.Windows.Extensions.Tests.exe
10,056,19210,050,048-6,144-0.061%System.Net.ServerSentEvents.Tests.exe
15,102,46415,093,248-9,216-0.061%System.Drawing.Primitives.Tests.exe
17,571,84017,561,088-10,752-0.061%MetricOuterLoop1.Tests.exe
17,566,72017,555,968-10,752-0.061%MetricOuterLoop.Tests.exe
19,289,60019,277,824-11,776-0.061%System.IO.Pipes.Tests.exe
17,791,48817,780,736-10,752-0.060%System.Formats.Tar.Manual.Tests.exe
17,967,61617,956,864-10,752-0.060%System.Threading.ThreadPool.WindowsThreadPool.Tests.exe
17,329,15217,318,912-10,240-0.059%System.Threading.Timer.Tests.exe
14,130,17614,121,984-8,192-0.058%System.DirectoryServices.Protocols.Tests.exe
17,616,89617,606,656-10,240-0.058%System.Threading.Thread.Tests.exe
19,681,79219,670,528-11,264-0.057%System.Net.Http.Unit.Tests.exe
17,160,19217,150,464-9,728-0.057%System.Runtime.Serialization.Formatters.Disabled.Tests.exe
17,967,10417,956,864-10,240-0.057%System.Threading.ThreadPool.Tests.exe
19,870,72019,859,456-11,264-0.057%System.Text.Encoding.Tests.exe
18,774,01618,763,264-10,752-0.057%Microsoft.Extensions.FileProviders.Physical.Tests.exe
27,160,06427,144,704-15,360-0.057%Microsoft.Extensions.Hosting.Unit.Tests.exe
17,214,97617,205,248-9,728-0.057%System.Net.ServicePoint.Tests.exe
17,312,76817,303,040-9,728-0.056%System.Security.Principal.Windows.Tests.exe
17,230,84817,221,120-9,728-0.056%System.ComponentModel.EventBasedAsync.Tests.exe
18,128,89618,118,656-10,240-0.056%System.Diagnostics.TextWriterTraceListener.Tests.exe
17,298,94417,289,216-9,728-0.056%System.Security.Claims.Tests.exe
17,431,04017,421,312-9,728-0.056%System.Diagnostics.TraceSource.Tests.exe
17,282,04817,272,320-9,728-0.056%System.Threading.Overlapped.Tests.exe
18,177,53618,167,296-10,240-0.056%System.Text.Encoding.CodePages.Tests.exe
17,356,28817,346,560-9,728-0.056%Microsoft.Win32.SystemEvents.Tests.exe
18,586,62418,576,384-10,240-0.055%ComInterfaceGenerator.Tests.exe
17,661,44017,651,712-9,728-0.055%System.IO.FileSystem.Watcher.Tests.exe
9,251,8409,246,720-5,120-0.055%Microsoft.Bcl.AsyncInterfaces.Tests.exe
13,941,24813,933,568-7,680-0.055%Microsoft.Extensions.Configuration.Xml.Tests.exe
18,492,92818,482,688-10,240-0.055%Microsoft.Extensions.Configuration.Tests.exe
17,662,97617,653,248-9,728-0.055%System.Buffers.Tests.exe
18,489,34418,479,104-10,240-0.055%Microsoft.Extensions.Hosting.Systemd.Tests.exe
15,080,44815,072,256-8,192-0.054%System.Security.Cryptography.Cng.Tests.exe
17,154,04817,144,832-9,216-0.054%IcuAppLocal.Tests.exe
15,039,48815,031,296-8,192-0.054%System.Data.DataSetExtensions.Tests.exe
18,062,33618,052,608-9,728-0.054%System.Console.Tests.exe
17,288,19217,278,976-9,216-0.053%System.Runtime.InteropServices.RuntimeInformation.Tests.exe
17,361,40817,352,192-9,216-0.053%System.Diagnostics.StackTrace.Tests.exe
18,455,55218,445,824-9,728-0.053%Microsoft.Extensions.Configuration.FileExtensions.Tests.exe
17,235,96817,226,752-9,216-0.053%System.Runtime.InvariantTimezone.Tests.exe
18,518,01618,508,288-9,728-0.053%System.IO.MemoryMappedFiles.Tests.exe
18,693,63218,683,904-9,728-0.052%Microsoft.Extensions.Logging.Console.Tests.exe
18,032,12818,022,912-9,216-0.051%Microsoft.Extensions.Diagnostics.Tests.exe
16,107,00816,098,816-8,192-0.051%System.Data.Odbc.Tests.exe
24,284,67224,272,384-12,288-0.051%Microsoft.Extensions.Http.Tests.exe
20,532,73620,522,496-10,240-0.050%System.Runtime.Extensions.Tests.exe
18,371,58418,362,368-9,216-0.050%System.Threading.Tests.exe
18,356,73618,347,520-9,216-0.050%Microsoft.Extensions.FileProviders.Composite.Tests.exe
18,381,82418,372,608-9,216-0.050%Microsoft.Extensions.Primitives.Tests.exe
11,331,07211,325,440-5,632-0.050%System.Net.WebSockets.Tests.exe
19,295,74419,286,016-9,728-0.050%System.Net.Primitives.Functional.Tests.exe
19,972,60819,962,880-9,728-0.049%Microsoft.Extensions.Logging.Tests.exe
11,588,09611,582,464-5,632-0.049%System.Net.Http.Json.Unit.Tests.exe
19,744,76819,735,040-9,728-0.049%System.Resources.ResourceManager.Tests.exe
9,334,7849,330,176-4,608-0.049%Microsoft.Extensions.Diagnostics.Abstractions.Tests.exe
18,833,92018,824,704-9,216-0.049%System.Runtime.Caching.Tests.exe
19,080,19219,070,976-9,216-0.048%Microsoft.Extensions.Hosting.WindowsServices.Tests.exe
9,660,4169,655,808-4,608-0.048%Microsoft.Extensions.Hosting.Functional.Tests.exe
20,475,90420,466,176-9,728-0.048%System.Diagnostics.DiagnosticSource.Tests.exe
20,741,63220,731,904-9,728-0.047%System.Collections.Concurrent.Tests.exe
10,106,36810,101,760-4,608-0.046%Microsoft.Extensions.Caching.Memory.Tests.exe
20,234,75220,225,536-9,216-0.046%System.Runtime.InteropServices.Tests.exe
20,454,91220,445,696-9,216-0.045%System.Reflection.Tests.exe
19,486,20819,477,504-8,704-0.045%Microsoft.Extensions.Configuration.UserSecrets.Tests.exe
11,274,24011,269,120-5,120-0.045%System.IO.Compression.Brotli.Tests.exe
19,555,84019,547,136-8,704-0.045%Microsoft.Extensions.Configuration.Json.Tests.exe
23,405,05623,394,816-10,240-0.044%System.Memory.Tests.exe
25,891,32825,880,064-11,264-0.044%System.Text.Json.SourceGeneration.Roslyn3.11.Tests.exe
10,510,33610,505,728-4,608-0.044%Microsoft.Extensions.Options.Tests.exe
9,442,8169,438,720-4,096-0.043%Microsoft.Extensions.Logging.Testing.Tests.exe
26,440,70426,429,440-11,264-0.043%System.ComponentModel.TypeConverter.Tests.exe
21,622,78421,613,568-9,216-0.043%System.Data.OleDb.Tests.exe
26,006,52825,996,288-10,240-0.039%System.Globalization.Nls.Tests.exe
20,808,70420,801,024-7,680-0.037%System.Security.Cryptography.Csp.Tests.exe
29,403,13629,392,384-10,752-0.037%Microsoft.Extensions.DependencyModel.Tests.exe
26,095,61626,085,888-9,728-0.037%System.Globalization.Tests.exe
21,072,38421,064,704-7,680-0.036%Microsoft.Extensions.Logging.EventSource.Tests.exe
45,486,08045,470,208-15,872-0.035%System.Security.Cryptography.Tests.exe
32,739,84032,730,112-9,728-0.030%System.Linq.Expressions.Tests.exe
33,385,98433,376,256-9,728-0.029%Microsoft.Bcl.Cryptography.Tests.exe
44,704,76844,693,504-11,264-0.025%System.Runtime.Tests.exe
2,233,3442,232,832-512-0.023%clrjit.dll
10,494,46410,492,928-1,536-0.015%System.Net.Http.WinHttpHandler.Unit.Tests.exe
10,586,11210,584,576-1,536-0.015%Common.Tests.exe
9,026,0489,025,024-1,024-0.011%Microsoft.Extensions.FileSystemGlobbing.Tests.exe
9,347,5849,346,560-1,024-0.011%System.Security.Permissions.Tests.exe
9,612,8009,611,776-1,024-0.011%System.Diagnostics.EventLog.Tests.exe
12,185,08812,184,064-1,024-0.008%System.Net.NetworkInformation.Functional.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Nls.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Tests.exe
8,743,9368,743,424-512-0.006%Invariant.Tests.exe
8,975,8728,975,360-512-0.006%System.Net.Primitives.Pal.Tests.exe
8,798,2088,797,696-512-0.006%System.Resources.Reader.Tests.exe
8,667,1368,666,624-512-0.006%System.Runtime.CompilerServices.Unsafe.Tests.exe
8,916,4808,915,968-512-0.006%System.IO.Pipes.AccessControl.Tests.exe
9,027,0729,026,560-512-0.006%System.Net.NameResolution.Pal.Tests.exe
9,191,9369,191,424-512-0.006%Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.exe
8,763,9048,763,392-512-0.006%Microsoft.Bcl.TimeProvider.Tests.exe
8,609,7928,609,280-512-0.006%System.Composition.Runtime.Tests.exe
9,129,4729,128,960-512-0.006%System.Security.AccessControl.Tests.exe
8,803,3288,802,816-512-0.006%System.Web.HttpUtility.Tests.exe
9,041,9209,041,408-512-0.006%Microsoft.Extensions.Configuration.CommandLine.Tests.exe
8,638,4648,637,952-512-0.006%System.Globalization.CalendarsWithConfigSwitch.Tests.exe
8,533,5048,532,992-512-0.006%System.ComponentModel.Tests.exe
8,686,5928,686,080-512-0.006%System.Security.Cryptography.ProtectedData.Tests.exe
8,755,7128,755,200-512-0.006%System.IO.FileSystem.DriveInfo.Tests.exe
8,977,4088,976,896-512-0.006%Microsoft.Win32.Registry.Tests.exe
8,685,5688,685,056-512-0.006%System.IO.FileSystem.Manual.Tests.exe
9,095,6809,095,168-512-0.006%System.IO.FileSystem.AccessControl.Tests.exe
10,048,51210,048,000-512-0.005%System.Diagnostics.Debug.Tests.exe
11,179,52011,179,008-512-0.005%System.Text.Encodings.Web.Tests.exe
11,034,11211,033,600-512-0.005%System.Runtime.Numerics.Tests.exe
11,363,32811,362,816-512-0.005%System.Net.Security.Unit.Tests.exe
9,337,3449,336,832-512-0.005%System.IO.IsolatedStorage.Tests.exe
9,748,9929,749,504+512+0.005%System.Formats.Asn1.Tests.exe
9,473,5369,473,024-512-0.005%Microsoft.Extensions.Configuration.Ini.Tests.exe
10,936,32010,935,808-512-0.005%System.Runtime.Intrinsics.Tests.exe
9,571,3289,570,816-512-0.005%System.Memory.Data.Tests.exe
9,660,9289,660,416-512-0.005%System.IO.UnmanagedMemoryStream.Tests.exe
9,524,7369,524,224-512-0.005%System.IO.Hashing.Tests.exe
9,361,9209,361,408-512-0.005%System.Net.Mail.Unit.Tests.exe
11,590,14411,589,632-512-0.004%System.Resources.Extensions.Tests.exe
11,469,31211,468,800-512-0.004%System.IO.Ports.Tests.exe
11,779,07211,778,560-512-0.004%System.Security.Cryptography.Cose.Tests.exe
17,824,76817,824,256-512-0.003%System.Collections.Tests.exe
18,770,43218,770,944+512+0.003%System.Numerics.Vectors.Tests.exe
22,320,64022,320,128-512-0.002%System.Security.Cryptography.Pkcs.Tests.exe
8,988,6728,988,67200.000%System.Runtime.Serialization.Primitives.Tests.exe
8,690,1768,690,17600.000%System.Security.SecureString.Tests.exe
9,201,6649,201,66400.000%System.ServiceProcess.ServiceController.Tests.exe
7,318,0167,318,01600.000%XUnitLogChecker.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
84,48084,48000.000%System.Globalization.Native.dll
108,032108,03200.000%CMakeCXXCompilerId.exe
108,032108,03200.000%CMakeCCompilerId.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
8,673,2808,673,28000.000%System.Runtime.InteropServices.ComDisabled.Tests.exe
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,608,7688,608,76800.000%System.Xml.Linq.Axes.Tests.exe
9,069,0569,069,05600.000%System.ValueTuple.Tests.exe
8,945,1528,945,15200.000%System.Threading.AccessControl.Tests.exe
9,690,1129,690,11200.000%System.Text.RegularExpressions.Unit.Tests.exe
8,543,2328,543,23200.000%System.Text.Encoding.Extensions.Tests.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
536,096536,09600.000%msquic.dll
8,529,4088,529,40800.000%System.IO.FileSystem.Primitives.Tests.exe
8,532,4808,532,48000.000%System.Runtime.CompilerServices.VisualC.Tests.exe
536,096536,09600.000%msquic.dll
1,308,6721,308,67200.000%mscordbi.dll
1,501,6961,501,69600.000%mscordaccore.dll
1,501,6961,501,69600.000%mscordaccore_amd64_amd64_42.42.42.42424.dll
361,984361,98400.000%hostpolicy.dll
350,208350,20800.000%hostfxr.dll
62,46462,46400.000%createdump.exe
210,944210,94400.000%corerun.exe
4,955,6484,955,64800.000%coreclr.dll
722,944722,94400.000%clrgcexp.dll
678,400678,40000.000%clrgc.dll
307,200307,20000.000%clretwrc.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
84,48084,48000.000%System.Globalization.Native.dll
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
696,320696,32000.000%FileCheck.exe
9,956,3529,956,35200.000%llvm-mca.exe
13,419,52013,419,52000.000%crossgen2.exe
7,703,0407,703,04000.000%ilasm.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
15,940,09615,940,09600.000%ilc.exe
8,938,4968,938,49600.000%Microsoft.Bcl.Memory.Tests.exe
8,578,0488,578,04800.000%Microsoft.Bcl.Numerics.Tests.exe
8,587,2648,587,26400.000%Microsoft.Extensions.Hosting.Abstractions.Tests.exe
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
9,947,6489,947,64800.000%LibraryImportGenerator.Tests.exe
8,655,8728,655,87200.000%System.Runtime.Handles.Tests.exe
16,973,82416,973,82400.000%System.Private.CoreLib.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
8,591,3608,591,36000.000%System.Resources.Writer.Tests.exe
9,011,2009,011,20000.000%System.Reflection.TypeExtensions.Tests.exe
12,271,10412,271,10400.000%System.Reflection.Metadata.Tests.exe
8,849,9208,849,92000.000%System.Reflection.Extensions.Tests.exe
9,350,6569,350,65600.000%System.Reflection.Context.Tests.exe
8,704,5128,704,51200.000%System.Private.Uri.Unit.Tests.exe
9,631,7449,631,74400.000%System.Private.Uri.Functional.Tests.exe
9,785,8569,785,85600.000%System.Net.WebProxy.Tests.exe
8,627,2008,627,20000.000%System.Net.WebHeaderCollection.Tests.exe
9,300,9929,300,99200.000%System.Net.Primitives.UnitTests.Tests.exe
15,486,97615,486,97600.000%System.Linq.Tests.exe
696,320696,32000.000%FileCheck.exe
9,150,9769,150,97600.000%System.Globalization.Calendars.Tests.exe
9,837,5689,837,56800.000%System.Formats.Nrbf.Tests.exe
8,534,5288,534,52800.000%System.Diagnostics.Tools.Tests.exe
8,702,4648,702,46400.000%System.Diagnostics.FileVersionInfo.Tests.exe
8,547,8408,547,84000.000%System.Diagnostics.Contracts.Tests.exe
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,649,2168,649,21600.000%Microsoft.Win32.Primitives.Tests.exe
9,934,3369,934,33600.000%System.Collections.NonGeneric.Tests.exe
9,734,6569,734,65600.000%System.Collections.Specialized.Tests.exe
9,147,3929,147,39200.000%System.ComponentModel.Primitives.Tests.exe
8,544,7688,544,76800.000%System.Composition.AttributeModel.Tests.exe
9,615,8729,615,87200.000%System.Composition.Convention.Tests.exe
8,821,7608,821,76000.000%System.Console.Manual.Tests.exe
8,632,8328,632,83200.000%Microsoft.Win32.Registry.AccessControl.Tests.exe
9,956,3529,956,35200.000%llvm-mca.exe

Remove `RestoreExecutionContext` call from JIT resumption code and from
the interpreter. Instead encode the `ExecutionContext`'s location in the
continuation and let the dispatcher restore it. This removes a TLS
access + helper call from the resumption path (avoiding the TLS and
inlining the helper call in the dispatcher).
Improves suspension/resumption performance by about 5-6% and should also
be a small size improvement.
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes CoreCLR runtime-async suspension/resumption so the dispatcher (managed AsyncHelpers) restores ExecutionContext, instead of having interpreter/JIT resumption stubs call a restore helper. The continuation’s flags now encode the ExecutionContext storage slot, enabling the dispatcher to restore without an extra TLS lookup + helper call on the hot resumption path.

Changes:

  • Add continuation support for locating/storing the ExecutionContext via encoded indices in continuation flags (VM + managed + JIT + interpreter).
  • Remove RestoreExecutionContext calls from interpreter and JIT resumption code; add restoration to the dispatcher loop.
  • Preserve BBF_ASYNC_RESUMPTION across certain flow optimizations that may bypass resumption stubs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/vm/object.hAdds VM helper to locate ExecutionContext storage in a continuation via encoded flag bits.
src/coreclr/vm/interpexec.cppWrites captured ExecutionContext via the encoded slot; removes interpreter-side restore on resume.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.csMoves ExecutionContext restore into dispatcher; adjusts flag layout and RestoreExecutionContext signature to avoid TLS lookup.
src/coreclr/jit/fgopt.cppCopies BBF_ASYNC_RESUMPTION during certain jump/switch/flow optimizations to preserve async side-entry affordances.
src/coreclr/jit/async.cppUpdates continuation layout/flag encoding for ExecutionContext; removes JIT-side restore on resumption.
src/coreclr/interpreter/inc/interpretershared.hRemoves interpreter suspend-data field that stored a raw execution-context offset.
src/coreclr/interpreter/compiler.cppEncodes ExecutionContext slot in flags and updates interpreter continuation layout accordingly.
src/coreclr/inc/corinfo.hUpdates CorInfoContinuationFlags bit assignments to include ExecutionContext index encoding.
Comments suppressed due to low confidence (2)

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:554

  • RuntimeAsyncStackState contains managed reference fields, but this local is left uninitialized before its address is stored in TLS (awaitState.Push(&stackState)). This can expose garbage references to the GC (and Push only initializes a subset of fields), risking GC crashes/corruption. Initialize stackState to default (or otherwise fully clear all reference fields before any GC safepoint) before calling Push.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:655

  • Same issue as in DispatchContinuations: RuntimeAsyncStackState stackState; is uninitialized even though the struct contains managed references and its address is pushed into TLS via awaitState.Push(&stackState). This can leave garbage object references visible to the GC until fields are explicitly set. Ensure stackState is zero-initialized (e.g., = default) or otherwise cleared before pushing.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

CopilotAI review requested due to automatic review settings April 29, 2026 09:11

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • InterpAsyncSuspendData.restoreExecutionContextMethod is still populated, but after removing the interpreter-side RestoreExecutionContext call there don’t appear to be any remaining reads of this field. Consider removing the field from InterpAsyncSuspendData (and this assignment) to reduce per-suspension metadata size and avoid dead state.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

CopilotAI review requested due to automatic review settings April 30, 2026 11:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • CORINFO_ASYNC_INFO no longer exposes restoreExecutionContextMethHnd, but the interpreter still stores asyncInfo.restoreExecutionContextMethHnd into InterpAsyncSuspendData. This will fail to compile and should be removed/rewired now that execution context restoration is done by the dispatcher.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

Comment threadsrc/coreclr/inc/corinfo.h
Comment threadsrc/coreclr/vm/corelib.h
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Comment threadsrc/coreclr/interpreter/inc/interpretershared.h
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Comment threadsrc/coreclr/jit/async.cpp
Comment threadsrc/coreclr/jit/fgbasic.cpp
CopilotAI review requested due to automatic review settings April 30, 2026 12:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 30, 2026 12:38

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/interpexec.cpp

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @VSadov (async) @AndyAyersMS (JIT) @davidwrighton /@janvorli (interpreter)

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT changes look good.

Comment threadsrc/coreclr/jit/fgbasic.cpp

@VSadovVSadov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Will merge this, @janvorli@davidwrighton let me know if you have any comments on the interpreter change and I can address it in a follow-up.

@jakobbotsch
jakobbotsch merged commit 83ebc00 into dotnet:mainMay 4, 2026
124 checks passed
@jakobbotsch
jakobbotsch deleted the restore-execution-context-in-dispatcher branch May 4, 2026 11:06
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@VSadov@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code - #127511

Merged
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher
May 4, 2026
Merged

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code#127511
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 28, 2026

Copy link
Copy Markdown
Member

Remove RestoreExecutionContext call from JIT resumption code and from the interpreter. Instead encode the ExecutionContext's location in the continuation and let the dispatcher restore it. This removes a TLS access + helper call from the resumption path (avoiding the TLS and inlining the helper call in the dispatcher).

Improves suspension/resumption performance by about 7-8% and is also a good size improvement. Removing the call from the resumption path allows keeping the continuation in a volatile register, which also helps register allocation in a number of cases.

Diffs before JIT-EE GUID update

Micro benchmark with warmup
usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceAsyncMicro;publicclassProgram{staticvoidMain(){NullAwaiterna=newNullAwaiter();for(inti=0;i<10;i++){for(intj=0;j<100;j++){Taskt=Foo(100,na);while(!t.IsCompleted){na.Continue();}}Thread.Sleep(100);}for(inti=0;i<50;i++){Taskt=Foo(10_000_000,na);while(!t.IsCompleted){na.Continue();}}}staticints_value;staticasyncTaskFoo(intn,NullAwaiterna){for(inti=0;i<n;i++){s_value+=i;}Stopwatchtimer=Stopwatch.StartNew();for(inti=0;i<n;i++){awaitna;}if(n>100)Console.WriteLine("Took {0:F1} ms",timer.Elapsed.TotalMilliseconds);}privateclassNullAwaiter:ICriticalNotifyCompletion{publicActionContinue;publicNullAwaiterGetAwaiter()=>this;publicboolIsCompleted=>false;publicvoidGetResult(){}publicvoidUnsafeOnCompleted(Actioncontinuation){Continue=continuation;}publicvoidOnCompleted(Actioncontinuation){thrownewNotImplementedException();}}}

About 7-8% improvement:

-Took 268.5 ms-Took 265.9 ms-Took 267.9 ms-Took 270.0 ms-Took 269.4 ms+Took 249.4 ms+Took 248.3 ms+Took 250.3 ms+Took 249.2 ms+Took 248.9 ms
NativeAOT test sizes
BaseSizeDiffSizeDeltaPercentName
31,037,44030,944,256-93,184-0.300%System.Net.Http.Functional.Tests.exe
16,847,87216,803,328-44,544-0.264%System.Linq.AsyncEnumerable.Tests.exe
115,269,120115,089,408-179,712-0.156%System.Text.Json.SourceGeneration.Roslyn4.4.Tests.exe
20,942,33620,912,640-29,696-0.142%System.Net.Quic.Functional.Tests.exe
20,033,02420,005,376-27,648-0.138%System.Formats.Tar.Tests.exe
19,558,91219,533,824-25,088-0.128%System.IO.Compression.Tests.exe
10,055,16810,042,880-12,288-0.122%System.IO.Compression.ZipFile.Tests.exe
14,901,76014,883,840-17,920-0.120%System.Xml.Linq.Streaming.Tests.exe
16,778,75216,758,784-19,968-0.119%System.Xml.Linq.Misc.Tests.exe
28,789,76028,757,504-32,256-0.112%System.Net.Http.WinHttpHandler.Functional.Tests.exe
16,516,60816,498,176-18,432-0.112%System.Xml.Linq.Events.Tests.exe
17,065,47217,046,528-18,944-0.111%System.Xml.Linq.xNodeBuilder.Tests.exe
22,732,80022,708,224-24,576-0.108%System.Net.Sockets.Tests.exe
16,671,74416,653,824-17,920-0.107%System.Xml.Linq.Properties.Tests.exe
17,123,84017,105,920-17,920-0.105%System.Xml.Linq.TreeManipulation.Tests.exe
17,007,61616,989,696-17,920-0.105%System.Xml.Linq.xNodeReader.Tests.exe
20,003,84019,982,848-20,992-0.105%System.Net.WebSockets.Client.Tests.exe
19,053,05619,034,112-18,944-0.099%System.Net.HttpListener.Tests.exe
10,660,86410,650,624-10,240-0.096%System.IO.Pipelines.Tests.exe
20,267,00820,248,064-18,944-0.093%System.Threading.Tasks.Dataflow.Tests.exe
17,728,51217,713,664-14,848-0.084%System.Threading.Tasks.Extensions.Tests.exe
14,569,47214,557,696-11,776-0.081%System.Net.WebClient.Tests.exe
11,992,06411,982,336-9,728-0.081%System.IO.Tests.exe
21,089,79221,072,896-16,896-0.080%System.Net.Requests.Tests.exe
21,708,80021,691,392-17,408-0.080%System.IO.FileSystem.Tests.exe
10,278,91210,270,720-8,192-0.080%System.Threading.Channels.Tests.exe
27,894,27227,874,304-19,968-0.072%System.Net.Security.Tests.exe
18,447,87218,434,560-13,312-0.072%System.Threading.Tasks.Parallel.Tests.exe
13,242,36813,233,152-9,216-0.070%System.IO.Packaging.Tests.exe
9,731,0729,724,416-6,656-0.068%System.Threading.RateLimiting.Tests.exe
33,165,31233,142,784-22,528-0.068%System.Private.Xml.Tests.exe
13,869,05613,859,840-9,216-0.066%Microsoft.Extensions.Configuration.Functional.Tests.exe
19,545,60019,532,800-12,800-0.065%System.Diagnostics.Process.Tests.exe
12,849,66412,841,472-8,192-0.064%System.Xml.Schema.Extensions.Tests.exe
12,416,00012,408,320-7,680-0.062%System.Xml.Linq.SDMSample.Tests.exe
17,431,55217,420,800-10,752-0.062%System.Net.Ping.Functional.Tests.exe
20,540,41620,527,616-12,800-0.062%System.Threading.Tasks.Tests.exe
15,759,87215,750,144-9,728-0.062%System.Windows.Extensions.Tests.exe
10,056,19210,050,048-6,144-0.061%System.Net.ServerSentEvents.Tests.exe
15,102,46415,093,248-9,216-0.061%System.Drawing.Primitives.Tests.exe
17,571,84017,561,088-10,752-0.061%MetricOuterLoop1.Tests.exe
17,566,72017,555,968-10,752-0.061%MetricOuterLoop.Tests.exe
19,289,60019,277,824-11,776-0.061%System.IO.Pipes.Tests.exe
17,791,48817,780,736-10,752-0.060%System.Formats.Tar.Manual.Tests.exe
17,967,61617,956,864-10,752-0.060%System.Threading.ThreadPool.WindowsThreadPool.Tests.exe
17,329,15217,318,912-10,240-0.059%System.Threading.Timer.Tests.exe
14,130,17614,121,984-8,192-0.058%System.DirectoryServices.Protocols.Tests.exe
17,616,89617,606,656-10,240-0.058%System.Threading.Thread.Tests.exe
19,681,79219,670,528-11,264-0.057%System.Net.Http.Unit.Tests.exe
17,160,19217,150,464-9,728-0.057%System.Runtime.Serialization.Formatters.Disabled.Tests.exe
17,967,10417,956,864-10,240-0.057%System.Threading.ThreadPool.Tests.exe
19,870,72019,859,456-11,264-0.057%System.Text.Encoding.Tests.exe
18,774,01618,763,264-10,752-0.057%Microsoft.Extensions.FileProviders.Physical.Tests.exe
27,160,06427,144,704-15,360-0.057%Microsoft.Extensions.Hosting.Unit.Tests.exe
17,214,97617,205,248-9,728-0.057%System.Net.ServicePoint.Tests.exe
17,312,76817,303,040-9,728-0.056%System.Security.Principal.Windows.Tests.exe
17,230,84817,221,120-9,728-0.056%System.ComponentModel.EventBasedAsync.Tests.exe
18,128,89618,118,656-10,240-0.056%System.Diagnostics.TextWriterTraceListener.Tests.exe
17,298,94417,289,216-9,728-0.056%System.Security.Claims.Tests.exe
17,431,04017,421,312-9,728-0.056%System.Diagnostics.TraceSource.Tests.exe
17,282,04817,272,320-9,728-0.056%System.Threading.Overlapped.Tests.exe
18,177,53618,167,296-10,240-0.056%System.Text.Encoding.CodePages.Tests.exe
17,356,28817,346,560-9,728-0.056%Microsoft.Win32.SystemEvents.Tests.exe
18,586,62418,576,384-10,240-0.055%ComInterfaceGenerator.Tests.exe
17,661,44017,651,712-9,728-0.055%System.IO.FileSystem.Watcher.Tests.exe
9,251,8409,246,720-5,120-0.055%Microsoft.Bcl.AsyncInterfaces.Tests.exe
13,941,24813,933,568-7,680-0.055%Microsoft.Extensions.Configuration.Xml.Tests.exe
18,492,92818,482,688-10,240-0.055%Microsoft.Extensions.Configuration.Tests.exe
17,662,97617,653,248-9,728-0.055%System.Buffers.Tests.exe
18,489,34418,479,104-10,240-0.055%Microsoft.Extensions.Hosting.Systemd.Tests.exe
15,080,44815,072,256-8,192-0.054%System.Security.Cryptography.Cng.Tests.exe
17,154,04817,144,832-9,216-0.054%IcuAppLocal.Tests.exe
15,039,48815,031,296-8,192-0.054%System.Data.DataSetExtensions.Tests.exe
18,062,33618,052,608-9,728-0.054%System.Console.Tests.exe
17,288,19217,278,976-9,216-0.053%System.Runtime.InteropServices.RuntimeInformation.Tests.exe
17,361,40817,352,192-9,216-0.053%System.Diagnostics.StackTrace.Tests.exe
18,455,55218,445,824-9,728-0.053%Microsoft.Extensions.Configuration.FileExtensions.Tests.exe
17,235,96817,226,752-9,216-0.053%System.Runtime.InvariantTimezone.Tests.exe
18,518,01618,508,288-9,728-0.053%System.IO.MemoryMappedFiles.Tests.exe
18,693,63218,683,904-9,728-0.052%Microsoft.Extensions.Logging.Console.Tests.exe
18,032,12818,022,912-9,216-0.051%Microsoft.Extensions.Diagnostics.Tests.exe
16,107,00816,098,816-8,192-0.051%System.Data.Odbc.Tests.exe
24,284,67224,272,384-12,288-0.051%Microsoft.Extensions.Http.Tests.exe
20,532,73620,522,496-10,240-0.050%System.Runtime.Extensions.Tests.exe
18,371,58418,362,368-9,216-0.050%System.Threading.Tests.exe
18,356,73618,347,520-9,216-0.050%Microsoft.Extensions.FileProviders.Composite.Tests.exe
18,381,82418,372,608-9,216-0.050%Microsoft.Extensions.Primitives.Tests.exe
11,331,07211,325,440-5,632-0.050%System.Net.WebSockets.Tests.exe
19,295,74419,286,016-9,728-0.050%System.Net.Primitives.Functional.Tests.exe
19,972,60819,962,880-9,728-0.049%Microsoft.Extensions.Logging.Tests.exe
11,588,09611,582,464-5,632-0.049%System.Net.Http.Json.Unit.Tests.exe
19,744,76819,735,040-9,728-0.049%System.Resources.ResourceManager.Tests.exe
9,334,7849,330,176-4,608-0.049%Microsoft.Extensions.Diagnostics.Abstractions.Tests.exe
18,833,92018,824,704-9,216-0.049%System.Runtime.Caching.Tests.exe
19,080,19219,070,976-9,216-0.048%Microsoft.Extensions.Hosting.WindowsServices.Tests.exe
9,660,4169,655,808-4,608-0.048%Microsoft.Extensions.Hosting.Functional.Tests.exe
20,475,90420,466,176-9,728-0.048%System.Diagnostics.DiagnosticSource.Tests.exe
20,741,63220,731,904-9,728-0.047%System.Collections.Concurrent.Tests.exe
10,106,36810,101,760-4,608-0.046%Microsoft.Extensions.Caching.Memory.Tests.exe
20,234,75220,225,536-9,216-0.046%System.Runtime.InteropServices.Tests.exe
20,454,91220,445,696-9,216-0.045%System.Reflection.Tests.exe
19,486,20819,477,504-8,704-0.045%Microsoft.Extensions.Configuration.UserSecrets.Tests.exe
11,274,24011,269,120-5,120-0.045%System.IO.Compression.Brotli.Tests.exe
19,555,84019,547,136-8,704-0.045%Microsoft.Extensions.Configuration.Json.Tests.exe
23,405,05623,394,816-10,240-0.044%System.Memory.Tests.exe
25,891,32825,880,064-11,264-0.044%System.Text.Json.SourceGeneration.Roslyn3.11.Tests.exe
10,510,33610,505,728-4,608-0.044%Microsoft.Extensions.Options.Tests.exe
9,442,8169,438,720-4,096-0.043%Microsoft.Extensions.Logging.Testing.Tests.exe
26,440,70426,429,440-11,264-0.043%System.ComponentModel.TypeConverter.Tests.exe
21,622,78421,613,568-9,216-0.043%System.Data.OleDb.Tests.exe
26,006,52825,996,288-10,240-0.039%System.Globalization.Nls.Tests.exe
20,808,70420,801,024-7,680-0.037%System.Security.Cryptography.Csp.Tests.exe
29,403,13629,392,384-10,752-0.037%Microsoft.Extensions.DependencyModel.Tests.exe
26,095,61626,085,888-9,728-0.037%System.Globalization.Tests.exe
21,072,38421,064,704-7,680-0.036%Microsoft.Extensions.Logging.EventSource.Tests.exe
45,486,08045,470,208-15,872-0.035%System.Security.Cryptography.Tests.exe
32,739,84032,730,112-9,728-0.030%System.Linq.Expressions.Tests.exe
33,385,98433,376,256-9,728-0.029%Microsoft.Bcl.Cryptography.Tests.exe
44,704,76844,693,504-11,264-0.025%System.Runtime.Tests.exe
2,233,3442,232,832-512-0.023%clrjit.dll
10,494,46410,492,928-1,536-0.015%System.Net.Http.WinHttpHandler.Unit.Tests.exe
10,586,11210,584,576-1,536-0.015%Common.Tests.exe
9,026,0489,025,024-1,024-0.011%Microsoft.Extensions.FileSystemGlobbing.Tests.exe
9,347,5849,346,560-1,024-0.011%System.Security.Permissions.Tests.exe
9,612,8009,611,776-1,024-0.011%System.Diagnostics.EventLog.Tests.exe
12,185,08812,184,064-1,024-0.008%System.Net.NetworkInformation.Functional.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Nls.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Tests.exe
8,743,9368,743,424-512-0.006%Invariant.Tests.exe
8,975,8728,975,360-512-0.006%System.Net.Primitives.Pal.Tests.exe
8,798,2088,797,696-512-0.006%System.Resources.Reader.Tests.exe
8,667,1368,666,624-512-0.006%System.Runtime.CompilerServices.Unsafe.Tests.exe
8,916,4808,915,968-512-0.006%System.IO.Pipes.AccessControl.Tests.exe
9,027,0729,026,560-512-0.006%System.Net.NameResolution.Pal.Tests.exe
9,191,9369,191,424-512-0.006%Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.exe
8,763,9048,763,392-512-0.006%Microsoft.Bcl.TimeProvider.Tests.exe
8,609,7928,609,280-512-0.006%System.Composition.Runtime.Tests.exe
9,129,4729,128,960-512-0.006%System.Security.AccessControl.Tests.exe
8,803,3288,802,816-512-0.006%System.Web.HttpUtility.Tests.exe
9,041,9209,041,408-512-0.006%Microsoft.Extensions.Configuration.CommandLine.Tests.exe
8,638,4648,637,952-512-0.006%System.Globalization.CalendarsWithConfigSwitch.Tests.exe
8,533,5048,532,992-512-0.006%System.ComponentModel.Tests.exe
8,686,5928,686,080-512-0.006%System.Security.Cryptography.ProtectedData.Tests.exe
8,755,7128,755,200-512-0.006%System.IO.FileSystem.DriveInfo.Tests.exe
8,977,4088,976,896-512-0.006%Microsoft.Win32.Registry.Tests.exe
8,685,5688,685,056-512-0.006%System.IO.FileSystem.Manual.Tests.exe
9,095,6809,095,168-512-0.006%System.IO.FileSystem.AccessControl.Tests.exe
10,048,51210,048,000-512-0.005%System.Diagnostics.Debug.Tests.exe
11,179,52011,179,008-512-0.005%System.Text.Encodings.Web.Tests.exe
11,034,11211,033,600-512-0.005%System.Runtime.Numerics.Tests.exe
11,363,32811,362,816-512-0.005%System.Net.Security.Unit.Tests.exe
9,337,3449,336,832-512-0.005%System.IO.IsolatedStorage.Tests.exe
9,748,9929,749,504+512+0.005%System.Formats.Asn1.Tests.exe
9,473,5369,473,024-512-0.005%Microsoft.Extensions.Configuration.Ini.Tests.exe
10,936,32010,935,808-512-0.005%System.Runtime.Intrinsics.Tests.exe
9,571,3289,570,816-512-0.005%System.Memory.Data.Tests.exe
9,660,9289,660,416-512-0.005%System.IO.UnmanagedMemoryStream.Tests.exe
9,524,7369,524,224-512-0.005%System.IO.Hashing.Tests.exe
9,361,9209,361,408-512-0.005%System.Net.Mail.Unit.Tests.exe
11,590,14411,589,632-512-0.004%System.Resources.Extensions.Tests.exe
11,469,31211,468,800-512-0.004%System.IO.Ports.Tests.exe
11,779,07211,778,560-512-0.004%System.Security.Cryptography.Cose.Tests.exe
17,824,76817,824,256-512-0.003%System.Collections.Tests.exe
18,770,43218,770,944+512+0.003%System.Numerics.Vectors.Tests.exe
22,320,64022,320,128-512-0.002%System.Security.Cryptography.Pkcs.Tests.exe
8,988,6728,988,67200.000%System.Runtime.Serialization.Primitives.Tests.exe
8,690,1768,690,17600.000%System.Security.SecureString.Tests.exe
9,201,6649,201,66400.000%System.ServiceProcess.ServiceController.Tests.exe
7,318,0167,318,01600.000%XUnitLogChecker.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
84,48084,48000.000%System.Globalization.Native.dll
108,032108,03200.000%CMakeCXXCompilerId.exe
108,032108,03200.000%CMakeCCompilerId.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
8,673,2808,673,28000.000%System.Runtime.InteropServices.ComDisabled.Tests.exe
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,608,7688,608,76800.000%System.Xml.Linq.Axes.Tests.exe
9,069,0569,069,05600.000%System.ValueTuple.Tests.exe
8,945,1528,945,15200.000%System.Threading.AccessControl.Tests.exe
9,690,1129,690,11200.000%System.Text.RegularExpressions.Unit.Tests.exe
8,543,2328,543,23200.000%System.Text.Encoding.Extensions.Tests.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
536,096536,09600.000%msquic.dll
8,529,4088,529,40800.000%System.IO.FileSystem.Primitives.Tests.exe
8,532,4808,532,48000.000%System.Runtime.CompilerServices.VisualC.Tests.exe
536,096536,09600.000%msquic.dll
1,308,6721,308,67200.000%mscordbi.dll
1,501,6961,501,69600.000%mscordaccore.dll
1,501,6961,501,69600.000%mscordaccore_amd64_amd64_42.42.42.42424.dll
361,984361,98400.000%hostpolicy.dll
350,208350,20800.000%hostfxr.dll
62,46462,46400.000%createdump.exe
210,944210,94400.000%corerun.exe
4,955,6484,955,64800.000%coreclr.dll
722,944722,94400.000%clrgcexp.dll
678,400678,40000.000%clrgc.dll
307,200307,20000.000%clretwrc.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
84,48084,48000.000%System.Globalization.Native.dll
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
696,320696,32000.000%FileCheck.exe
9,956,3529,956,35200.000%llvm-mca.exe
13,419,52013,419,52000.000%crossgen2.exe
7,703,0407,703,04000.000%ilasm.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
15,940,09615,940,09600.000%ilc.exe
8,938,4968,938,49600.000%Microsoft.Bcl.Memory.Tests.exe
8,578,0488,578,04800.000%Microsoft.Bcl.Numerics.Tests.exe
8,587,2648,587,26400.000%Microsoft.Extensions.Hosting.Abstractions.Tests.exe
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
9,947,6489,947,64800.000%LibraryImportGenerator.Tests.exe
8,655,8728,655,87200.000%System.Runtime.Handles.Tests.exe
16,973,82416,973,82400.000%System.Private.CoreLib.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
8,591,3608,591,36000.000%System.Resources.Writer.Tests.exe
9,011,2009,011,20000.000%System.Reflection.TypeExtensions.Tests.exe
12,271,10412,271,10400.000%System.Reflection.Metadata.Tests.exe
8,849,9208,849,92000.000%System.Reflection.Extensions.Tests.exe
9,350,6569,350,65600.000%System.Reflection.Context.Tests.exe
8,704,5128,704,51200.000%System.Private.Uri.Unit.Tests.exe
9,631,7449,631,74400.000%System.Private.Uri.Functional.Tests.exe
9,785,8569,785,85600.000%System.Net.WebProxy.Tests.exe
8,627,2008,627,20000.000%System.Net.WebHeaderCollection.Tests.exe
9,300,9929,300,99200.000%System.Net.Primitives.UnitTests.Tests.exe
15,486,97615,486,97600.000%System.Linq.Tests.exe
696,320696,32000.000%FileCheck.exe
9,150,9769,150,97600.000%System.Globalization.Calendars.Tests.exe
9,837,5689,837,56800.000%System.Formats.Nrbf.Tests.exe
8,534,5288,534,52800.000%System.Diagnostics.Tools.Tests.exe
8,702,4648,702,46400.000%System.Diagnostics.FileVersionInfo.Tests.exe
8,547,8408,547,84000.000%System.Diagnostics.Contracts.Tests.exe
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,649,2168,649,21600.000%Microsoft.Win32.Primitives.Tests.exe
9,934,3369,934,33600.000%System.Collections.NonGeneric.Tests.exe
9,734,6569,734,65600.000%System.Collections.Specialized.Tests.exe
9,147,3929,147,39200.000%System.ComponentModel.Primitives.Tests.exe
8,544,7688,544,76800.000%System.Composition.AttributeModel.Tests.exe
9,615,8729,615,87200.000%System.Composition.Convention.Tests.exe
8,821,7608,821,76000.000%System.Console.Manual.Tests.exe
8,632,8328,632,83200.000%Microsoft.Win32.Registry.AccessControl.Tests.exe
9,956,3529,956,35200.000%llvm-mca.exe

Remove `RestoreExecutionContext` call from JIT resumption code and from
the interpreter. Instead encode the `ExecutionContext`'s location in the
continuation and let the dispatcher restore it. This removes a TLS
access + helper call from the resumption path (avoiding the TLS and
inlining the helper call in the dispatcher).
Improves suspension/resumption performance by about 5-6% and should also
be a small size improvement.
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes CoreCLR runtime-async suspension/resumption so the dispatcher (managed AsyncHelpers) restores ExecutionContext, instead of having interpreter/JIT resumption stubs call a restore helper. The continuation’s flags now encode the ExecutionContext storage slot, enabling the dispatcher to restore without an extra TLS lookup + helper call on the hot resumption path.

Changes:

  • Add continuation support for locating/storing the ExecutionContext via encoded indices in continuation flags (VM + managed + JIT + interpreter).
  • Remove RestoreExecutionContext calls from interpreter and JIT resumption code; add restoration to the dispatcher loop.
  • Preserve BBF_ASYNC_RESUMPTION across certain flow optimizations that may bypass resumption stubs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/vm/object.hAdds VM helper to locate ExecutionContext storage in a continuation via encoded flag bits.
src/coreclr/vm/interpexec.cppWrites captured ExecutionContext via the encoded slot; removes interpreter-side restore on resume.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.csMoves ExecutionContext restore into dispatcher; adjusts flag layout and RestoreExecutionContext signature to avoid TLS lookup.
src/coreclr/jit/fgopt.cppCopies BBF_ASYNC_RESUMPTION during certain jump/switch/flow optimizations to preserve async side-entry affordances.
src/coreclr/jit/async.cppUpdates continuation layout/flag encoding for ExecutionContext; removes JIT-side restore on resumption.
src/coreclr/interpreter/inc/interpretershared.hRemoves interpreter suspend-data field that stored a raw execution-context offset.
src/coreclr/interpreter/compiler.cppEncodes ExecutionContext slot in flags and updates interpreter continuation layout accordingly.
src/coreclr/inc/corinfo.hUpdates CorInfoContinuationFlags bit assignments to include ExecutionContext index encoding.
Comments suppressed due to low confidence (2)

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:554

  • RuntimeAsyncStackState contains managed reference fields, but this local is left uninitialized before its address is stored in TLS (awaitState.Push(&stackState)). This can expose garbage references to the GC (and Push only initializes a subset of fields), risking GC crashes/corruption. Initialize stackState to default (or otherwise fully clear all reference fields before any GC safepoint) before calling Push.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:655

  • Same issue as in DispatchContinuations: RuntimeAsyncStackState stackState; is uninitialized even though the struct contains managed references and its address is pushed into TLS via awaitState.Push(&stackState). This can leave garbage object references visible to the GC until fields are explicitly set. Ensure stackState is zero-initialized (e.g., = default) or otherwise cleared before pushing.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

CopilotAI review requested due to automatic review settings April 29, 2026 09:11

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • InterpAsyncSuspendData.restoreExecutionContextMethod is still populated, but after removing the interpreter-side RestoreExecutionContext call there don’t appear to be any remaining reads of this field. Consider removing the field from InterpAsyncSuspendData (and this assignment) to reduce per-suspension metadata size and avoid dead state.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

CopilotAI review requested due to automatic review settings April 30, 2026 11:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • CORINFO_ASYNC_INFO no longer exposes restoreExecutionContextMethHnd, but the interpreter still stores asyncInfo.restoreExecutionContextMethHnd into InterpAsyncSuspendData. This will fail to compile and should be removed/rewired now that execution context restoration is done by the dispatcher.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

Comment threadsrc/coreclr/inc/corinfo.h
Comment threadsrc/coreclr/vm/corelib.h
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Comment threadsrc/coreclr/interpreter/inc/interpretershared.h
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Comment threadsrc/coreclr/jit/async.cpp
Comment threadsrc/coreclr/jit/fgbasic.cpp
CopilotAI review requested due to automatic review settings April 30, 2026 12:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 30, 2026 12:38

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/interpexec.cpp

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @VSadov (async) @AndyAyersMS (JIT) @davidwrighton /@janvorli (interpreter)

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT changes look good.

Comment threadsrc/coreclr/jit/fgbasic.cpp

@VSadovVSadov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Will merge this, @janvorli@davidwrighton let me know if you have any comments on the interpreter change and I can address it in a follow-up.

@jakobbotsch
jakobbotsch merged commit 83ebc00 into dotnet:mainMay 4, 2026
124 checks passed
@jakobbotsch
jakobbotsch deleted the restore-execution-context-in-dispatcher branch May 4, 2026 11:06
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@VSadov@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code - #127511

Merged
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher
May 4, 2026
Merged

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code#127511
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 28, 2026

Copy link
Copy Markdown
Member

Remove RestoreExecutionContext call from JIT resumption code and from the interpreter. Instead encode the ExecutionContext's location in the continuation and let the dispatcher restore it. This removes a TLS access + helper call from the resumption path (avoiding the TLS and inlining the helper call in the dispatcher).

Improves suspension/resumption performance by about 7-8% and is also a good size improvement. Removing the call from the resumption path allows keeping the continuation in a volatile register, which also helps register allocation in a number of cases.

Diffs before JIT-EE GUID update

Micro benchmark with warmup
usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceAsyncMicro;publicclassProgram{staticvoidMain(){NullAwaiterna=newNullAwaiter();for(inti=0;i<10;i++){for(intj=0;j<100;j++){Taskt=Foo(100,na);while(!t.IsCompleted){na.Continue();}}Thread.Sleep(100);}for(inti=0;i<50;i++){Taskt=Foo(10_000_000,na);while(!t.IsCompleted){na.Continue();}}}staticints_value;staticasyncTaskFoo(intn,NullAwaiterna){for(inti=0;i<n;i++){s_value+=i;}Stopwatchtimer=Stopwatch.StartNew();for(inti=0;i<n;i++){awaitna;}if(n>100)Console.WriteLine("Took {0:F1} ms",timer.Elapsed.TotalMilliseconds);}privateclassNullAwaiter:ICriticalNotifyCompletion{publicActionContinue;publicNullAwaiterGetAwaiter()=>this;publicboolIsCompleted=>false;publicvoidGetResult(){}publicvoidUnsafeOnCompleted(Actioncontinuation){Continue=continuation;}publicvoidOnCompleted(Actioncontinuation){thrownewNotImplementedException();}}}

About 7-8% improvement:

-Took 268.5 ms-Took 265.9 ms-Took 267.9 ms-Took 270.0 ms-Took 269.4 ms+Took 249.4 ms+Took 248.3 ms+Took 250.3 ms+Took 249.2 ms+Took 248.9 ms
NativeAOT test sizes
BaseSizeDiffSizeDeltaPercentName
31,037,44030,944,256-93,184-0.300%System.Net.Http.Functional.Tests.exe
16,847,87216,803,328-44,544-0.264%System.Linq.AsyncEnumerable.Tests.exe
115,269,120115,089,408-179,712-0.156%System.Text.Json.SourceGeneration.Roslyn4.4.Tests.exe
20,942,33620,912,640-29,696-0.142%System.Net.Quic.Functional.Tests.exe
20,033,02420,005,376-27,648-0.138%System.Formats.Tar.Tests.exe
19,558,91219,533,824-25,088-0.128%System.IO.Compression.Tests.exe
10,055,16810,042,880-12,288-0.122%System.IO.Compression.ZipFile.Tests.exe
14,901,76014,883,840-17,920-0.120%System.Xml.Linq.Streaming.Tests.exe
16,778,75216,758,784-19,968-0.119%System.Xml.Linq.Misc.Tests.exe
28,789,76028,757,504-32,256-0.112%System.Net.Http.WinHttpHandler.Functional.Tests.exe
16,516,60816,498,176-18,432-0.112%System.Xml.Linq.Events.Tests.exe
17,065,47217,046,528-18,944-0.111%System.Xml.Linq.xNodeBuilder.Tests.exe
22,732,80022,708,224-24,576-0.108%System.Net.Sockets.Tests.exe
16,671,74416,653,824-17,920-0.107%System.Xml.Linq.Properties.Tests.exe
17,123,84017,105,920-17,920-0.105%System.Xml.Linq.TreeManipulation.Tests.exe
17,007,61616,989,696-17,920-0.105%System.Xml.Linq.xNodeReader.Tests.exe
20,003,84019,982,848-20,992-0.105%System.Net.WebSockets.Client.Tests.exe
19,053,05619,034,112-18,944-0.099%System.Net.HttpListener.Tests.exe
10,660,86410,650,624-10,240-0.096%System.IO.Pipelines.Tests.exe
20,267,00820,248,064-18,944-0.093%System.Threading.Tasks.Dataflow.Tests.exe
17,728,51217,713,664-14,848-0.084%System.Threading.Tasks.Extensions.Tests.exe
14,569,47214,557,696-11,776-0.081%System.Net.WebClient.Tests.exe
11,992,06411,982,336-9,728-0.081%System.IO.Tests.exe
21,089,79221,072,896-16,896-0.080%System.Net.Requests.Tests.exe
21,708,80021,691,392-17,408-0.080%System.IO.FileSystem.Tests.exe
10,278,91210,270,720-8,192-0.080%System.Threading.Channels.Tests.exe
27,894,27227,874,304-19,968-0.072%System.Net.Security.Tests.exe
18,447,87218,434,560-13,312-0.072%System.Threading.Tasks.Parallel.Tests.exe
13,242,36813,233,152-9,216-0.070%System.IO.Packaging.Tests.exe
9,731,0729,724,416-6,656-0.068%System.Threading.RateLimiting.Tests.exe
33,165,31233,142,784-22,528-0.068%System.Private.Xml.Tests.exe
13,869,05613,859,840-9,216-0.066%Microsoft.Extensions.Configuration.Functional.Tests.exe
19,545,60019,532,800-12,800-0.065%System.Diagnostics.Process.Tests.exe
12,849,66412,841,472-8,192-0.064%System.Xml.Schema.Extensions.Tests.exe
12,416,00012,408,320-7,680-0.062%System.Xml.Linq.SDMSample.Tests.exe
17,431,55217,420,800-10,752-0.062%System.Net.Ping.Functional.Tests.exe
20,540,41620,527,616-12,800-0.062%System.Threading.Tasks.Tests.exe
15,759,87215,750,144-9,728-0.062%System.Windows.Extensions.Tests.exe
10,056,19210,050,048-6,144-0.061%System.Net.ServerSentEvents.Tests.exe
15,102,46415,093,248-9,216-0.061%System.Drawing.Primitives.Tests.exe
17,571,84017,561,088-10,752-0.061%MetricOuterLoop1.Tests.exe
17,566,72017,555,968-10,752-0.061%MetricOuterLoop.Tests.exe
19,289,60019,277,824-11,776-0.061%System.IO.Pipes.Tests.exe
17,791,48817,780,736-10,752-0.060%System.Formats.Tar.Manual.Tests.exe
17,967,61617,956,864-10,752-0.060%System.Threading.ThreadPool.WindowsThreadPool.Tests.exe
17,329,15217,318,912-10,240-0.059%System.Threading.Timer.Tests.exe
14,130,17614,121,984-8,192-0.058%System.DirectoryServices.Protocols.Tests.exe
17,616,89617,606,656-10,240-0.058%System.Threading.Thread.Tests.exe
19,681,79219,670,528-11,264-0.057%System.Net.Http.Unit.Tests.exe
17,160,19217,150,464-9,728-0.057%System.Runtime.Serialization.Formatters.Disabled.Tests.exe
17,967,10417,956,864-10,240-0.057%System.Threading.ThreadPool.Tests.exe
19,870,72019,859,456-11,264-0.057%System.Text.Encoding.Tests.exe
18,774,01618,763,264-10,752-0.057%Microsoft.Extensions.FileProviders.Physical.Tests.exe
27,160,06427,144,704-15,360-0.057%Microsoft.Extensions.Hosting.Unit.Tests.exe
17,214,97617,205,248-9,728-0.057%System.Net.ServicePoint.Tests.exe
17,312,76817,303,040-9,728-0.056%System.Security.Principal.Windows.Tests.exe
17,230,84817,221,120-9,728-0.056%System.ComponentModel.EventBasedAsync.Tests.exe
18,128,89618,118,656-10,240-0.056%System.Diagnostics.TextWriterTraceListener.Tests.exe
17,298,94417,289,216-9,728-0.056%System.Security.Claims.Tests.exe
17,431,04017,421,312-9,728-0.056%System.Diagnostics.TraceSource.Tests.exe
17,282,04817,272,320-9,728-0.056%System.Threading.Overlapped.Tests.exe
18,177,53618,167,296-10,240-0.056%System.Text.Encoding.CodePages.Tests.exe
17,356,28817,346,560-9,728-0.056%Microsoft.Win32.SystemEvents.Tests.exe
18,586,62418,576,384-10,240-0.055%ComInterfaceGenerator.Tests.exe
17,661,44017,651,712-9,728-0.055%System.IO.FileSystem.Watcher.Tests.exe
9,251,8409,246,720-5,120-0.055%Microsoft.Bcl.AsyncInterfaces.Tests.exe
13,941,24813,933,568-7,680-0.055%Microsoft.Extensions.Configuration.Xml.Tests.exe
18,492,92818,482,688-10,240-0.055%Microsoft.Extensions.Configuration.Tests.exe
17,662,97617,653,248-9,728-0.055%System.Buffers.Tests.exe
18,489,34418,479,104-10,240-0.055%Microsoft.Extensions.Hosting.Systemd.Tests.exe
15,080,44815,072,256-8,192-0.054%System.Security.Cryptography.Cng.Tests.exe
17,154,04817,144,832-9,216-0.054%IcuAppLocal.Tests.exe
15,039,48815,031,296-8,192-0.054%System.Data.DataSetExtensions.Tests.exe
18,062,33618,052,608-9,728-0.054%System.Console.Tests.exe
17,288,19217,278,976-9,216-0.053%System.Runtime.InteropServices.RuntimeInformation.Tests.exe
17,361,40817,352,192-9,216-0.053%System.Diagnostics.StackTrace.Tests.exe
18,455,55218,445,824-9,728-0.053%Microsoft.Extensions.Configuration.FileExtensions.Tests.exe
17,235,96817,226,752-9,216-0.053%System.Runtime.InvariantTimezone.Tests.exe
18,518,01618,508,288-9,728-0.053%System.IO.MemoryMappedFiles.Tests.exe
18,693,63218,683,904-9,728-0.052%Microsoft.Extensions.Logging.Console.Tests.exe
18,032,12818,022,912-9,216-0.051%Microsoft.Extensions.Diagnostics.Tests.exe
16,107,00816,098,816-8,192-0.051%System.Data.Odbc.Tests.exe
24,284,67224,272,384-12,288-0.051%Microsoft.Extensions.Http.Tests.exe
20,532,73620,522,496-10,240-0.050%System.Runtime.Extensions.Tests.exe
18,371,58418,362,368-9,216-0.050%System.Threading.Tests.exe
18,356,73618,347,520-9,216-0.050%Microsoft.Extensions.FileProviders.Composite.Tests.exe
18,381,82418,372,608-9,216-0.050%Microsoft.Extensions.Primitives.Tests.exe
11,331,07211,325,440-5,632-0.050%System.Net.WebSockets.Tests.exe
19,295,74419,286,016-9,728-0.050%System.Net.Primitives.Functional.Tests.exe
19,972,60819,962,880-9,728-0.049%Microsoft.Extensions.Logging.Tests.exe
11,588,09611,582,464-5,632-0.049%System.Net.Http.Json.Unit.Tests.exe
19,744,76819,735,040-9,728-0.049%System.Resources.ResourceManager.Tests.exe
9,334,7849,330,176-4,608-0.049%Microsoft.Extensions.Diagnostics.Abstractions.Tests.exe
18,833,92018,824,704-9,216-0.049%System.Runtime.Caching.Tests.exe
19,080,19219,070,976-9,216-0.048%Microsoft.Extensions.Hosting.WindowsServices.Tests.exe
9,660,4169,655,808-4,608-0.048%Microsoft.Extensions.Hosting.Functional.Tests.exe
20,475,90420,466,176-9,728-0.048%System.Diagnostics.DiagnosticSource.Tests.exe
20,741,63220,731,904-9,728-0.047%System.Collections.Concurrent.Tests.exe
10,106,36810,101,760-4,608-0.046%Microsoft.Extensions.Caching.Memory.Tests.exe
20,234,75220,225,536-9,216-0.046%System.Runtime.InteropServices.Tests.exe
20,454,91220,445,696-9,216-0.045%System.Reflection.Tests.exe
19,486,20819,477,504-8,704-0.045%Microsoft.Extensions.Configuration.UserSecrets.Tests.exe
11,274,24011,269,120-5,120-0.045%System.IO.Compression.Brotli.Tests.exe
19,555,84019,547,136-8,704-0.045%Microsoft.Extensions.Configuration.Json.Tests.exe
23,405,05623,394,816-10,240-0.044%System.Memory.Tests.exe
25,891,32825,880,064-11,264-0.044%System.Text.Json.SourceGeneration.Roslyn3.11.Tests.exe
10,510,33610,505,728-4,608-0.044%Microsoft.Extensions.Options.Tests.exe
9,442,8169,438,720-4,096-0.043%Microsoft.Extensions.Logging.Testing.Tests.exe
26,440,70426,429,440-11,264-0.043%System.ComponentModel.TypeConverter.Tests.exe
21,622,78421,613,568-9,216-0.043%System.Data.OleDb.Tests.exe
26,006,52825,996,288-10,240-0.039%System.Globalization.Nls.Tests.exe
20,808,70420,801,024-7,680-0.037%System.Security.Cryptography.Csp.Tests.exe
29,403,13629,392,384-10,752-0.037%Microsoft.Extensions.DependencyModel.Tests.exe
26,095,61626,085,888-9,728-0.037%System.Globalization.Tests.exe
21,072,38421,064,704-7,680-0.036%Microsoft.Extensions.Logging.EventSource.Tests.exe
45,486,08045,470,208-15,872-0.035%System.Security.Cryptography.Tests.exe
32,739,84032,730,112-9,728-0.030%System.Linq.Expressions.Tests.exe
33,385,98433,376,256-9,728-0.029%Microsoft.Bcl.Cryptography.Tests.exe
44,704,76844,693,504-11,264-0.025%System.Runtime.Tests.exe
2,233,3442,232,832-512-0.023%clrjit.dll
10,494,46410,492,928-1,536-0.015%System.Net.Http.WinHttpHandler.Unit.Tests.exe
10,586,11210,584,576-1,536-0.015%Common.Tests.exe
9,026,0489,025,024-1,024-0.011%Microsoft.Extensions.FileSystemGlobbing.Tests.exe
9,347,5849,346,560-1,024-0.011%System.Security.Permissions.Tests.exe
9,612,8009,611,776-1,024-0.011%System.Diagnostics.EventLog.Tests.exe
12,185,08812,184,064-1,024-0.008%System.Net.NetworkInformation.Functional.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Nls.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Tests.exe
8,743,9368,743,424-512-0.006%Invariant.Tests.exe
8,975,8728,975,360-512-0.006%System.Net.Primitives.Pal.Tests.exe
8,798,2088,797,696-512-0.006%System.Resources.Reader.Tests.exe
8,667,1368,666,624-512-0.006%System.Runtime.CompilerServices.Unsafe.Tests.exe
8,916,4808,915,968-512-0.006%System.IO.Pipes.AccessControl.Tests.exe
9,027,0729,026,560-512-0.006%System.Net.NameResolution.Pal.Tests.exe
9,191,9369,191,424-512-0.006%Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.exe
8,763,9048,763,392-512-0.006%Microsoft.Bcl.TimeProvider.Tests.exe
8,609,7928,609,280-512-0.006%System.Composition.Runtime.Tests.exe
9,129,4729,128,960-512-0.006%System.Security.AccessControl.Tests.exe
8,803,3288,802,816-512-0.006%System.Web.HttpUtility.Tests.exe
9,041,9209,041,408-512-0.006%Microsoft.Extensions.Configuration.CommandLine.Tests.exe
8,638,4648,637,952-512-0.006%System.Globalization.CalendarsWithConfigSwitch.Tests.exe
8,533,5048,532,992-512-0.006%System.ComponentModel.Tests.exe
8,686,5928,686,080-512-0.006%System.Security.Cryptography.ProtectedData.Tests.exe
8,755,7128,755,200-512-0.006%System.IO.FileSystem.DriveInfo.Tests.exe
8,977,4088,976,896-512-0.006%Microsoft.Win32.Registry.Tests.exe
8,685,5688,685,056-512-0.006%System.IO.FileSystem.Manual.Tests.exe
9,095,6809,095,168-512-0.006%System.IO.FileSystem.AccessControl.Tests.exe
10,048,51210,048,000-512-0.005%System.Diagnostics.Debug.Tests.exe
11,179,52011,179,008-512-0.005%System.Text.Encodings.Web.Tests.exe
11,034,11211,033,600-512-0.005%System.Runtime.Numerics.Tests.exe
11,363,32811,362,816-512-0.005%System.Net.Security.Unit.Tests.exe
9,337,3449,336,832-512-0.005%System.IO.IsolatedStorage.Tests.exe
9,748,9929,749,504+512+0.005%System.Formats.Asn1.Tests.exe
9,473,5369,473,024-512-0.005%Microsoft.Extensions.Configuration.Ini.Tests.exe
10,936,32010,935,808-512-0.005%System.Runtime.Intrinsics.Tests.exe
9,571,3289,570,816-512-0.005%System.Memory.Data.Tests.exe
9,660,9289,660,416-512-0.005%System.IO.UnmanagedMemoryStream.Tests.exe
9,524,7369,524,224-512-0.005%System.IO.Hashing.Tests.exe
9,361,9209,361,408-512-0.005%System.Net.Mail.Unit.Tests.exe
11,590,14411,589,632-512-0.004%System.Resources.Extensions.Tests.exe
11,469,31211,468,800-512-0.004%System.IO.Ports.Tests.exe
11,779,07211,778,560-512-0.004%System.Security.Cryptography.Cose.Tests.exe
17,824,76817,824,256-512-0.003%System.Collections.Tests.exe
18,770,43218,770,944+512+0.003%System.Numerics.Vectors.Tests.exe
22,320,64022,320,128-512-0.002%System.Security.Cryptography.Pkcs.Tests.exe
8,988,6728,988,67200.000%System.Runtime.Serialization.Primitives.Tests.exe
8,690,1768,690,17600.000%System.Security.SecureString.Tests.exe
9,201,6649,201,66400.000%System.ServiceProcess.ServiceController.Tests.exe
7,318,0167,318,01600.000%XUnitLogChecker.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
84,48084,48000.000%System.Globalization.Native.dll
108,032108,03200.000%CMakeCXXCompilerId.exe
108,032108,03200.000%CMakeCCompilerId.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
8,673,2808,673,28000.000%System.Runtime.InteropServices.ComDisabled.Tests.exe
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,608,7688,608,76800.000%System.Xml.Linq.Axes.Tests.exe
9,069,0569,069,05600.000%System.ValueTuple.Tests.exe
8,945,1528,945,15200.000%System.Threading.AccessControl.Tests.exe
9,690,1129,690,11200.000%System.Text.RegularExpressions.Unit.Tests.exe
8,543,2328,543,23200.000%System.Text.Encoding.Extensions.Tests.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
536,096536,09600.000%msquic.dll
8,529,4088,529,40800.000%System.IO.FileSystem.Primitives.Tests.exe
8,532,4808,532,48000.000%System.Runtime.CompilerServices.VisualC.Tests.exe
536,096536,09600.000%msquic.dll
1,308,6721,308,67200.000%mscordbi.dll
1,501,6961,501,69600.000%mscordaccore.dll
1,501,6961,501,69600.000%mscordaccore_amd64_amd64_42.42.42.42424.dll
361,984361,98400.000%hostpolicy.dll
350,208350,20800.000%hostfxr.dll
62,46462,46400.000%createdump.exe
210,944210,94400.000%corerun.exe
4,955,6484,955,64800.000%coreclr.dll
722,944722,94400.000%clrgcexp.dll
678,400678,40000.000%clrgc.dll
307,200307,20000.000%clretwrc.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
84,48084,48000.000%System.Globalization.Native.dll
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
696,320696,32000.000%FileCheck.exe
9,956,3529,956,35200.000%llvm-mca.exe
13,419,52013,419,52000.000%crossgen2.exe
7,703,0407,703,04000.000%ilasm.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
15,940,09615,940,09600.000%ilc.exe
8,938,4968,938,49600.000%Microsoft.Bcl.Memory.Tests.exe
8,578,0488,578,04800.000%Microsoft.Bcl.Numerics.Tests.exe
8,587,2648,587,26400.000%Microsoft.Extensions.Hosting.Abstractions.Tests.exe
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
9,947,6489,947,64800.000%LibraryImportGenerator.Tests.exe
8,655,8728,655,87200.000%System.Runtime.Handles.Tests.exe
16,973,82416,973,82400.000%System.Private.CoreLib.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
8,591,3608,591,36000.000%System.Resources.Writer.Tests.exe
9,011,2009,011,20000.000%System.Reflection.TypeExtensions.Tests.exe
12,271,10412,271,10400.000%System.Reflection.Metadata.Tests.exe
8,849,9208,849,92000.000%System.Reflection.Extensions.Tests.exe
9,350,6569,350,65600.000%System.Reflection.Context.Tests.exe
8,704,5128,704,51200.000%System.Private.Uri.Unit.Tests.exe
9,631,7449,631,74400.000%System.Private.Uri.Functional.Tests.exe
9,785,8569,785,85600.000%System.Net.WebProxy.Tests.exe
8,627,2008,627,20000.000%System.Net.WebHeaderCollection.Tests.exe
9,300,9929,300,99200.000%System.Net.Primitives.UnitTests.Tests.exe
15,486,97615,486,97600.000%System.Linq.Tests.exe
696,320696,32000.000%FileCheck.exe
9,150,9769,150,97600.000%System.Globalization.Calendars.Tests.exe
9,837,5689,837,56800.000%System.Formats.Nrbf.Tests.exe
8,534,5288,534,52800.000%System.Diagnostics.Tools.Tests.exe
8,702,4648,702,46400.000%System.Diagnostics.FileVersionInfo.Tests.exe
8,547,8408,547,84000.000%System.Diagnostics.Contracts.Tests.exe
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,649,2168,649,21600.000%Microsoft.Win32.Primitives.Tests.exe
9,934,3369,934,33600.000%System.Collections.NonGeneric.Tests.exe
9,734,6569,734,65600.000%System.Collections.Specialized.Tests.exe
9,147,3929,147,39200.000%System.ComponentModel.Primitives.Tests.exe
8,544,7688,544,76800.000%System.Composition.AttributeModel.Tests.exe
9,615,8729,615,87200.000%System.Composition.Convention.Tests.exe
8,821,7608,821,76000.000%System.Console.Manual.Tests.exe
8,632,8328,632,83200.000%Microsoft.Win32.Registry.AccessControl.Tests.exe
9,956,3529,956,35200.000%llvm-mca.exe

Remove `RestoreExecutionContext` call from JIT resumption code and from
the interpreter. Instead encode the `ExecutionContext`'s location in the
continuation and let the dispatcher restore it. This removes a TLS
access + helper call from the resumption path (avoiding the TLS and
inlining the helper call in the dispatcher).
Improves suspension/resumption performance by about 5-6% and should also
be a small size improvement.
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes CoreCLR runtime-async suspension/resumption so the dispatcher (managed AsyncHelpers) restores ExecutionContext, instead of having interpreter/JIT resumption stubs call a restore helper. The continuation’s flags now encode the ExecutionContext storage slot, enabling the dispatcher to restore without an extra TLS lookup + helper call on the hot resumption path.

Changes:

  • Add continuation support for locating/storing the ExecutionContext via encoded indices in continuation flags (VM + managed + JIT + interpreter).
  • Remove RestoreExecutionContext calls from interpreter and JIT resumption code; add restoration to the dispatcher loop.
  • Preserve BBF_ASYNC_RESUMPTION across certain flow optimizations that may bypass resumption stubs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/vm/object.hAdds VM helper to locate ExecutionContext storage in a continuation via encoded flag bits.
src/coreclr/vm/interpexec.cppWrites captured ExecutionContext via the encoded slot; removes interpreter-side restore on resume.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.csMoves ExecutionContext restore into dispatcher; adjusts flag layout and RestoreExecutionContext signature to avoid TLS lookup.
src/coreclr/jit/fgopt.cppCopies BBF_ASYNC_RESUMPTION during certain jump/switch/flow optimizations to preserve async side-entry affordances.
src/coreclr/jit/async.cppUpdates continuation layout/flag encoding for ExecutionContext; removes JIT-side restore on resumption.
src/coreclr/interpreter/inc/interpretershared.hRemoves interpreter suspend-data field that stored a raw execution-context offset.
src/coreclr/interpreter/compiler.cppEncodes ExecutionContext slot in flags and updates interpreter continuation layout accordingly.
src/coreclr/inc/corinfo.hUpdates CorInfoContinuationFlags bit assignments to include ExecutionContext index encoding.
Comments suppressed due to low confidence (2)

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:554

  • RuntimeAsyncStackState contains managed reference fields, but this local is left uninitialized before its address is stored in TLS (awaitState.Push(&stackState)). This can expose garbage references to the GC (and Push only initializes a subset of fields), risking GC crashes/corruption. Initialize stackState to default (or otherwise fully clear all reference fields before any GC safepoint) before calling Push.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:655

  • Same issue as in DispatchContinuations: RuntimeAsyncStackState stackState; is uninitialized even though the struct contains managed references and its address is pushed into TLS via awaitState.Push(&stackState). This can leave garbage object references visible to the GC until fields are explicitly set. Ensure stackState is zero-initialized (e.g., = default) or otherwise cleared before pushing.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

CopilotAI review requested due to automatic review settings April 29, 2026 09:11

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • InterpAsyncSuspendData.restoreExecutionContextMethod is still populated, but after removing the interpreter-side RestoreExecutionContext call there don’t appear to be any remaining reads of this field. Consider removing the field from InterpAsyncSuspendData (and this assignment) to reduce per-suspension metadata size and avoid dead state.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

CopilotAI review requested due to automatic review settings April 30, 2026 11:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • CORINFO_ASYNC_INFO no longer exposes restoreExecutionContextMethHnd, but the interpreter still stores asyncInfo.restoreExecutionContextMethHnd into InterpAsyncSuspendData. This will fail to compile and should be removed/rewired now that execution context restoration is done by the dispatcher.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

Comment threadsrc/coreclr/inc/corinfo.h
Comment threadsrc/coreclr/vm/corelib.h
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Comment threadsrc/coreclr/interpreter/inc/interpretershared.h
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Comment threadsrc/coreclr/jit/async.cpp
Comment threadsrc/coreclr/jit/fgbasic.cpp
CopilotAI review requested due to automatic review settings April 30, 2026 12:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 30, 2026 12:38

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/interpexec.cpp

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @VSadov (async) @AndyAyersMS (JIT) @davidwrighton /@janvorli (interpreter)

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT changes look good.

Comment threadsrc/coreclr/jit/fgbasic.cpp

@VSadovVSadov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Will merge this, @janvorli@davidwrighton let me know if you have any comments on the interpreter change and I can address it in a follow-up.

@jakobbotsch
jakobbotsch merged commit 83ebc00 into dotnet:mainMay 4, 2026
124 checks passed
@jakobbotsch
jakobbotsch deleted the restore-execution-context-in-dispatcher branch May 4, 2026 11:06
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@VSadov@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code - #127511

Merged
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher
May 4, 2026
Merged

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code#127511
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 28, 2026

Copy link
Copy Markdown
Member

Remove RestoreExecutionContext call from JIT resumption code and from the interpreter. Instead encode the ExecutionContext's location in the continuation and let the dispatcher restore it. This removes a TLS access + helper call from the resumption path (avoiding the TLS and inlining the helper call in the dispatcher).

Improves suspension/resumption performance by about 7-8% and is also a good size improvement. Removing the call from the resumption path allows keeping the continuation in a volatile register, which also helps register allocation in a number of cases.

Diffs before JIT-EE GUID update

Micro benchmark with warmup
usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceAsyncMicro;publicclassProgram{staticvoidMain(){NullAwaiterna=newNullAwaiter();for(inti=0;i<10;i++){for(intj=0;j<100;j++){Taskt=Foo(100,na);while(!t.IsCompleted){na.Continue();}}Thread.Sleep(100);}for(inti=0;i<50;i++){Taskt=Foo(10_000_000,na);while(!t.IsCompleted){na.Continue();}}}staticints_value;staticasyncTaskFoo(intn,NullAwaiterna){for(inti=0;i<n;i++){s_value+=i;}Stopwatchtimer=Stopwatch.StartNew();for(inti=0;i<n;i++){awaitna;}if(n>100)Console.WriteLine("Took {0:F1} ms",timer.Elapsed.TotalMilliseconds);}privateclassNullAwaiter:ICriticalNotifyCompletion{publicActionContinue;publicNullAwaiterGetAwaiter()=>this;publicboolIsCompleted=>false;publicvoidGetResult(){}publicvoidUnsafeOnCompleted(Actioncontinuation){Continue=continuation;}publicvoidOnCompleted(Actioncontinuation){thrownewNotImplementedException();}}}

About 7-8% improvement:

-Took 268.5 ms-Took 265.9 ms-Took 267.9 ms-Took 270.0 ms-Took 269.4 ms+Took 249.4 ms+Took 248.3 ms+Took 250.3 ms+Took 249.2 ms+Took 248.9 ms
NativeAOT test sizes
BaseSizeDiffSizeDeltaPercentName
31,037,44030,944,256-93,184-0.300%System.Net.Http.Functional.Tests.exe
16,847,87216,803,328-44,544-0.264%System.Linq.AsyncEnumerable.Tests.exe
115,269,120115,089,408-179,712-0.156%System.Text.Json.SourceGeneration.Roslyn4.4.Tests.exe
20,942,33620,912,640-29,696-0.142%System.Net.Quic.Functional.Tests.exe
20,033,02420,005,376-27,648-0.138%System.Formats.Tar.Tests.exe
19,558,91219,533,824-25,088-0.128%System.IO.Compression.Tests.exe
10,055,16810,042,880-12,288-0.122%System.IO.Compression.ZipFile.Tests.exe
14,901,76014,883,840-17,920-0.120%System.Xml.Linq.Streaming.Tests.exe
16,778,75216,758,784-19,968-0.119%System.Xml.Linq.Misc.Tests.exe
28,789,76028,757,504-32,256-0.112%System.Net.Http.WinHttpHandler.Functional.Tests.exe
16,516,60816,498,176-18,432-0.112%System.Xml.Linq.Events.Tests.exe
17,065,47217,046,528-18,944-0.111%System.Xml.Linq.xNodeBuilder.Tests.exe
22,732,80022,708,224-24,576-0.108%System.Net.Sockets.Tests.exe
16,671,74416,653,824-17,920-0.107%System.Xml.Linq.Properties.Tests.exe
17,123,84017,105,920-17,920-0.105%System.Xml.Linq.TreeManipulation.Tests.exe
17,007,61616,989,696-17,920-0.105%System.Xml.Linq.xNodeReader.Tests.exe
20,003,84019,982,848-20,992-0.105%System.Net.WebSockets.Client.Tests.exe
19,053,05619,034,112-18,944-0.099%System.Net.HttpListener.Tests.exe
10,660,86410,650,624-10,240-0.096%System.IO.Pipelines.Tests.exe
20,267,00820,248,064-18,944-0.093%System.Threading.Tasks.Dataflow.Tests.exe
17,728,51217,713,664-14,848-0.084%System.Threading.Tasks.Extensions.Tests.exe
14,569,47214,557,696-11,776-0.081%System.Net.WebClient.Tests.exe
11,992,06411,982,336-9,728-0.081%System.IO.Tests.exe
21,089,79221,072,896-16,896-0.080%System.Net.Requests.Tests.exe
21,708,80021,691,392-17,408-0.080%System.IO.FileSystem.Tests.exe
10,278,91210,270,720-8,192-0.080%System.Threading.Channels.Tests.exe
27,894,27227,874,304-19,968-0.072%System.Net.Security.Tests.exe
18,447,87218,434,560-13,312-0.072%System.Threading.Tasks.Parallel.Tests.exe
13,242,36813,233,152-9,216-0.070%System.IO.Packaging.Tests.exe
9,731,0729,724,416-6,656-0.068%System.Threading.RateLimiting.Tests.exe
33,165,31233,142,784-22,528-0.068%System.Private.Xml.Tests.exe
13,869,05613,859,840-9,216-0.066%Microsoft.Extensions.Configuration.Functional.Tests.exe
19,545,60019,532,800-12,800-0.065%System.Diagnostics.Process.Tests.exe
12,849,66412,841,472-8,192-0.064%System.Xml.Schema.Extensions.Tests.exe
12,416,00012,408,320-7,680-0.062%System.Xml.Linq.SDMSample.Tests.exe
17,431,55217,420,800-10,752-0.062%System.Net.Ping.Functional.Tests.exe
20,540,41620,527,616-12,800-0.062%System.Threading.Tasks.Tests.exe
15,759,87215,750,144-9,728-0.062%System.Windows.Extensions.Tests.exe
10,056,19210,050,048-6,144-0.061%System.Net.ServerSentEvents.Tests.exe
15,102,46415,093,248-9,216-0.061%System.Drawing.Primitives.Tests.exe
17,571,84017,561,088-10,752-0.061%MetricOuterLoop1.Tests.exe
17,566,72017,555,968-10,752-0.061%MetricOuterLoop.Tests.exe
19,289,60019,277,824-11,776-0.061%System.IO.Pipes.Tests.exe
17,791,48817,780,736-10,752-0.060%System.Formats.Tar.Manual.Tests.exe
17,967,61617,956,864-10,752-0.060%System.Threading.ThreadPool.WindowsThreadPool.Tests.exe
17,329,15217,318,912-10,240-0.059%System.Threading.Timer.Tests.exe
14,130,17614,121,984-8,192-0.058%System.DirectoryServices.Protocols.Tests.exe
17,616,89617,606,656-10,240-0.058%System.Threading.Thread.Tests.exe
19,681,79219,670,528-11,264-0.057%System.Net.Http.Unit.Tests.exe
17,160,19217,150,464-9,728-0.057%System.Runtime.Serialization.Formatters.Disabled.Tests.exe
17,967,10417,956,864-10,240-0.057%System.Threading.ThreadPool.Tests.exe
19,870,72019,859,456-11,264-0.057%System.Text.Encoding.Tests.exe
18,774,01618,763,264-10,752-0.057%Microsoft.Extensions.FileProviders.Physical.Tests.exe
27,160,06427,144,704-15,360-0.057%Microsoft.Extensions.Hosting.Unit.Tests.exe
17,214,97617,205,248-9,728-0.057%System.Net.ServicePoint.Tests.exe
17,312,76817,303,040-9,728-0.056%System.Security.Principal.Windows.Tests.exe
17,230,84817,221,120-9,728-0.056%System.ComponentModel.EventBasedAsync.Tests.exe
18,128,89618,118,656-10,240-0.056%System.Diagnostics.TextWriterTraceListener.Tests.exe
17,298,94417,289,216-9,728-0.056%System.Security.Claims.Tests.exe
17,431,04017,421,312-9,728-0.056%System.Diagnostics.TraceSource.Tests.exe
17,282,04817,272,320-9,728-0.056%System.Threading.Overlapped.Tests.exe
18,177,53618,167,296-10,240-0.056%System.Text.Encoding.CodePages.Tests.exe
17,356,28817,346,560-9,728-0.056%Microsoft.Win32.SystemEvents.Tests.exe
18,586,62418,576,384-10,240-0.055%ComInterfaceGenerator.Tests.exe
17,661,44017,651,712-9,728-0.055%System.IO.FileSystem.Watcher.Tests.exe
9,251,8409,246,720-5,120-0.055%Microsoft.Bcl.AsyncInterfaces.Tests.exe
13,941,24813,933,568-7,680-0.055%Microsoft.Extensions.Configuration.Xml.Tests.exe
18,492,92818,482,688-10,240-0.055%Microsoft.Extensions.Configuration.Tests.exe
17,662,97617,653,248-9,728-0.055%System.Buffers.Tests.exe
18,489,34418,479,104-10,240-0.055%Microsoft.Extensions.Hosting.Systemd.Tests.exe
15,080,44815,072,256-8,192-0.054%System.Security.Cryptography.Cng.Tests.exe
17,154,04817,144,832-9,216-0.054%IcuAppLocal.Tests.exe
15,039,48815,031,296-8,192-0.054%System.Data.DataSetExtensions.Tests.exe
18,062,33618,052,608-9,728-0.054%System.Console.Tests.exe
17,288,19217,278,976-9,216-0.053%System.Runtime.InteropServices.RuntimeInformation.Tests.exe
17,361,40817,352,192-9,216-0.053%System.Diagnostics.StackTrace.Tests.exe
18,455,55218,445,824-9,728-0.053%Microsoft.Extensions.Configuration.FileExtensions.Tests.exe
17,235,96817,226,752-9,216-0.053%System.Runtime.InvariantTimezone.Tests.exe
18,518,01618,508,288-9,728-0.053%System.IO.MemoryMappedFiles.Tests.exe
18,693,63218,683,904-9,728-0.052%Microsoft.Extensions.Logging.Console.Tests.exe
18,032,12818,022,912-9,216-0.051%Microsoft.Extensions.Diagnostics.Tests.exe
16,107,00816,098,816-8,192-0.051%System.Data.Odbc.Tests.exe
24,284,67224,272,384-12,288-0.051%Microsoft.Extensions.Http.Tests.exe
20,532,73620,522,496-10,240-0.050%System.Runtime.Extensions.Tests.exe
18,371,58418,362,368-9,216-0.050%System.Threading.Tests.exe
18,356,73618,347,520-9,216-0.050%Microsoft.Extensions.FileProviders.Composite.Tests.exe
18,381,82418,372,608-9,216-0.050%Microsoft.Extensions.Primitives.Tests.exe
11,331,07211,325,440-5,632-0.050%System.Net.WebSockets.Tests.exe
19,295,74419,286,016-9,728-0.050%System.Net.Primitives.Functional.Tests.exe
19,972,60819,962,880-9,728-0.049%Microsoft.Extensions.Logging.Tests.exe
11,588,09611,582,464-5,632-0.049%System.Net.Http.Json.Unit.Tests.exe
19,744,76819,735,040-9,728-0.049%System.Resources.ResourceManager.Tests.exe
9,334,7849,330,176-4,608-0.049%Microsoft.Extensions.Diagnostics.Abstractions.Tests.exe
18,833,92018,824,704-9,216-0.049%System.Runtime.Caching.Tests.exe
19,080,19219,070,976-9,216-0.048%Microsoft.Extensions.Hosting.WindowsServices.Tests.exe
9,660,4169,655,808-4,608-0.048%Microsoft.Extensions.Hosting.Functional.Tests.exe
20,475,90420,466,176-9,728-0.048%System.Diagnostics.DiagnosticSource.Tests.exe
20,741,63220,731,904-9,728-0.047%System.Collections.Concurrent.Tests.exe
10,106,36810,101,760-4,608-0.046%Microsoft.Extensions.Caching.Memory.Tests.exe
20,234,75220,225,536-9,216-0.046%System.Runtime.InteropServices.Tests.exe
20,454,91220,445,696-9,216-0.045%System.Reflection.Tests.exe
19,486,20819,477,504-8,704-0.045%Microsoft.Extensions.Configuration.UserSecrets.Tests.exe
11,274,24011,269,120-5,120-0.045%System.IO.Compression.Brotli.Tests.exe
19,555,84019,547,136-8,704-0.045%Microsoft.Extensions.Configuration.Json.Tests.exe
23,405,05623,394,816-10,240-0.044%System.Memory.Tests.exe
25,891,32825,880,064-11,264-0.044%System.Text.Json.SourceGeneration.Roslyn3.11.Tests.exe
10,510,33610,505,728-4,608-0.044%Microsoft.Extensions.Options.Tests.exe
9,442,8169,438,720-4,096-0.043%Microsoft.Extensions.Logging.Testing.Tests.exe
26,440,70426,429,440-11,264-0.043%System.ComponentModel.TypeConverter.Tests.exe
21,622,78421,613,568-9,216-0.043%System.Data.OleDb.Tests.exe
26,006,52825,996,288-10,240-0.039%System.Globalization.Nls.Tests.exe
20,808,70420,801,024-7,680-0.037%System.Security.Cryptography.Csp.Tests.exe
29,403,13629,392,384-10,752-0.037%Microsoft.Extensions.DependencyModel.Tests.exe
26,095,61626,085,888-9,728-0.037%System.Globalization.Tests.exe
21,072,38421,064,704-7,680-0.036%Microsoft.Extensions.Logging.EventSource.Tests.exe
45,486,08045,470,208-15,872-0.035%System.Security.Cryptography.Tests.exe
32,739,84032,730,112-9,728-0.030%System.Linq.Expressions.Tests.exe
33,385,98433,376,256-9,728-0.029%Microsoft.Bcl.Cryptography.Tests.exe
44,704,76844,693,504-11,264-0.025%System.Runtime.Tests.exe
2,233,3442,232,832-512-0.023%clrjit.dll
10,494,46410,492,928-1,536-0.015%System.Net.Http.WinHttpHandler.Unit.Tests.exe
10,586,11210,584,576-1,536-0.015%Common.Tests.exe
9,026,0489,025,024-1,024-0.011%Microsoft.Extensions.FileSystemGlobbing.Tests.exe
9,347,5849,346,560-1,024-0.011%System.Security.Permissions.Tests.exe
9,612,8009,611,776-1,024-0.011%System.Diagnostics.EventLog.Tests.exe
12,185,08812,184,064-1,024-0.008%System.Net.NetworkInformation.Functional.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Nls.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Tests.exe
8,743,9368,743,424-512-0.006%Invariant.Tests.exe
8,975,8728,975,360-512-0.006%System.Net.Primitives.Pal.Tests.exe
8,798,2088,797,696-512-0.006%System.Resources.Reader.Tests.exe
8,667,1368,666,624-512-0.006%System.Runtime.CompilerServices.Unsafe.Tests.exe
8,916,4808,915,968-512-0.006%System.IO.Pipes.AccessControl.Tests.exe
9,027,0729,026,560-512-0.006%System.Net.NameResolution.Pal.Tests.exe
9,191,9369,191,424-512-0.006%Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.exe
8,763,9048,763,392-512-0.006%Microsoft.Bcl.TimeProvider.Tests.exe
8,609,7928,609,280-512-0.006%System.Composition.Runtime.Tests.exe
9,129,4729,128,960-512-0.006%System.Security.AccessControl.Tests.exe
8,803,3288,802,816-512-0.006%System.Web.HttpUtility.Tests.exe
9,041,9209,041,408-512-0.006%Microsoft.Extensions.Configuration.CommandLine.Tests.exe
8,638,4648,637,952-512-0.006%System.Globalization.CalendarsWithConfigSwitch.Tests.exe
8,533,5048,532,992-512-0.006%System.ComponentModel.Tests.exe
8,686,5928,686,080-512-0.006%System.Security.Cryptography.ProtectedData.Tests.exe
8,755,7128,755,200-512-0.006%System.IO.FileSystem.DriveInfo.Tests.exe
8,977,4088,976,896-512-0.006%Microsoft.Win32.Registry.Tests.exe
8,685,5688,685,056-512-0.006%System.IO.FileSystem.Manual.Tests.exe
9,095,6809,095,168-512-0.006%System.IO.FileSystem.AccessControl.Tests.exe
10,048,51210,048,000-512-0.005%System.Diagnostics.Debug.Tests.exe
11,179,52011,179,008-512-0.005%System.Text.Encodings.Web.Tests.exe
11,034,11211,033,600-512-0.005%System.Runtime.Numerics.Tests.exe
11,363,32811,362,816-512-0.005%System.Net.Security.Unit.Tests.exe
9,337,3449,336,832-512-0.005%System.IO.IsolatedStorage.Tests.exe
9,748,9929,749,504+512+0.005%System.Formats.Asn1.Tests.exe
9,473,5369,473,024-512-0.005%Microsoft.Extensions.Configuration.Ini.Tests.exe
10,936,32010,935,808-512-0.005%System.Runtime.Intrinsics.Tests.exe
9,571,3289,570,816-512-0.005%System.Memory.Data.Tests.exe
9,660,9289,660,416-512-0.005%System.IO.UnmanagedMemoryStream.Tests.exe
9,524,7369,524,224-512-0.005%System.IO.Hashing.Tests.exe
9,361,9209,361,408-512-0.005%System.Net.Mail.Unit.Tests.exe
11,590,14411,589,632-512-0.004%System.Resources.Extensions.Tests.exe
11,469,31211,468,800-512-0.004%System.IO.Ports.Tests.exe
11,779,07211,778,560-512-0.004%System.Security.Cryptography.Cose.Tests.exe
17,824,76817,824,256-512-0.003%System.Collections.Tests.exe
18,770,43218,770,944+512+0.003%System.Numerics.Vectors.Tests.exe
22,320,64022,320,128-512-0.002%System.Security.Cryptography.Pkcs.Tests.exe
8,988,6728,988,67200.000%System.Runtime.Serialization.Primitives.Tests.exe
8,690,1768,690,17600.000%System.Security.SecureString.Tests.exe
9,201,6649,201,66400.000%System.ServiceProcess.ServiceController.Tests.exe
7,318,0167,318,01600.000%XUnitLogChecker.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
84,48084,48000.000%System.Globalization.Native.dll
108,032108,03200.000%CMakeCXXCompilerId.exe
108,032108,03200.000%CMakeCCompilerId.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
8,673,2808,673,28000.000%System.Runtime.InteropServices.ComDisabled.Tests.exe
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,608,7688,608,76800.000%System.Xml.Linq.Axes.Tests.exe
9,069,0569,069,05600.000%System.ValueTuple.Tests.exe
8,945,1528,945,15200.000%System.Threading.AccessControl.Tests.exe
9,690,1129,690,11200.000%System.Text.RegularExpressions.Unit.Tests.exe
8,543,2328,543,23200.000%System.Text.Encoding.Extensions.Tests.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
536,096536,09600.000%msquic.dll
8,529,4088,529,40800.000%System.IO.FileSystem.Primitives.Tests.exe
8,532,4808,532,48000.000%System.Runtime.CompilerServices.VisualC.Tests.exe
536,096536,09600.000%msquic.dll
1,308,6721,308,67200.000%mscordbi.dll
1,501,6961,501,69600.000%mscordaccore.dll
1,501,6961,501,69600.000%mscordaccore_amd64_amd64_42.42.42.42424.dll
361,984361,98400.000%hostpolicy.dll
350,208350,20800.000%hostfxr.dll
62,46462,46400.000%createdump.exe
210,944210,94400.000%corerun.exe
4,955,6484,955,64800.000%coreclr.dll
722,944722,94400.000%clrgcexp.dll
678,400678,40000.000%clrgc.dll
307,200307,20000.000%clretwrc.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
84,48084,48000.000%System.Globalization.Native.dll
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
696,320696,32000.000%FileCheck.exe
9,956,3529,956,35200.000%llvm-mca.exe
13,419,52013,419,52000.000%crossgen2.exe
7,703,0407,703,04000.000%ilasm.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
15,940,09615,940,09600.000%ilc.exe
8,938,4968,938,49600.000%Microsoft.Bcl.Memory.Tests.exe
8,578,0488,578,04800.000%Microsoft.Bcl.Numerics.Tests.exe
8,587,2648,587,26400.000%Microsoft.Extensions.Hosting.Abstractions.Tests.exe
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
9,947,6489,947,64800.000%LibraryImportGenerator.Tests.exe
8,655,8728,655,87200.000%System.Runtime.Handles.Tests.exe
16,973,82416,973,82400.000%System.Private.CoreLib.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
8,591,3608,591,36000.000%System.Resources.Writer.Tests.exe
9,011,2009,011,20000.000%System.Reflection.TypeExtensions.Tests.exe
12,271,10412,271,10400.000%System.Reflection.Metadata.Tests.exe
8,849,9208,849,92000.000%System.Reflection.Extensions.Tests.exe
9,350,6569,350,65600.000%System.Reflection.Context.Tests.exe
8,704,5128,704,51200.000%System.Private.Uri.Unit.Tests.exe
9,631,7449,631,74400.000%System.Private.Uri.Functional.Tests.exe
9,785,8569,785,85600.000%System.Net.WebProxy.Tests.exe
8,627,2008,627,20000.000%System.Net.WebHeaderCollection.Tests.exe
9,300,9929,300,99200.000%System.Net.Primitives.UnitTests.Tests.exe
15,486,97615,486,97600.000%System.Linq.Tests.exe
696,320696,32000.000%FileCheck.exe
9,150,9769,150,97600.000%System.Globalization.Calendars.Tests.exe
9,837,5689,837,56800.000%System.Formats.Nrbf.Tests.exe
8,534,5288,534,52800.000%System.Diagnostics.Tools.Tests.exe
8,702,4648,702,46400.000%System.Diagnostics.FileVersionInfo.Tests.exe
8,547,8408,547,84000.000%System.Diagnostics.Contracts.Tests.exe
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,649,2168,649,21600.000%Microsoft.Win32.Primitives.Tests.exe
9,934,3369,934,33600.000%System.Collections.NonGeneric.Tests.exe
9,734,6569,734,65600.000%System.Collections.Specialized.Tests.exe
9,147,3929,147,39200.000%System.ComponentModel.Primitives.Tests.exe
8,544,7688,544,76800.000%System.Composition.AttributeModel.Tests.exe
9,615,8729,615,87200.000%System.Composition.Convention.Tests.exe
8,821,7608,821,76000.000%System.Console.Manual.Tests.exe
8,632,8328,632,83200.000%Microsoft.Win32.Registry.AccessControl.Tests.exe
9,956,3529,956,35200.000%llvm-mca.exe

Remove `RestoreExecutionContext` call from JIT resumption code and from
the interpreter. Instead encode the `ExecutionContext`'s location in the
continuation and let the dispatcher restore it. This removes a TLS
access + helper call from the resumption path (avoiding the TLS and
inlining the helper call in the dispatcher).
Improves suspension/resumption performance by about 5-6% and should also
be a small size improvement.
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes CoreCLR runtime-async suspension/resumption so the dispatcher (managed AsyncHelpers) restores ExecutionContext, instead of having interpreter/JIT resumption stubs call a restore helper. The continuation’s flags now encode the ExecutionContext storage slot, enabling the dispatcher to restore without an extra TLS lookup + helper call on the hot resumption path.

Changes:

  • Add continuation support for locating/storing the ExecutionContext via encoded indices in continuation flags (VM + managed + JIT + interpreter).
  • Remove RestoreExecutionContext calls from interpreter and JIT resumption code; add restoration to the dispatcher loop.
  • Preserve BBF_ASYNC_RESUMPTION across certain flow optimizations that may bypass resumption stubs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/vm/object.hAdds VM helper to locate ExecutionContext storage in a continuation via encoded flag bits.
src/coreclr/vm/interpexec.cppWrites captured ExecutionContext via the encoded slot; removes interpreter-side restore on resume.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.csMoves ExecutionContext restore into dispatcher; adjusts flag layout and RestoreExecutionContext signature to avoid TLS lookup.
src/coreclr/jit/fgopt.cppCopies BBF_ASYNC_RESUMPTION during certain jump/switch/flow optimizations to preserve async side-entry affordances.
src/coreclr/jit/async.cppUpdates continuation layout/flag encoding for ExecutionContext; removes JIT-side restore on resumption.
src/coreclr/interpreter/inc/interpretershared.hRemoves interpreter suspend-data field that stored a raw execution-context offset.
src/coreclr/interpreter/compiler.cppEncodes ExecutionContext slot in flags and updates interpreter continuation layout accordingly.
src/coreclr/inc/corinfo.hUpdates CorInfoContinuationFlags bit assignments to include ExecutionContext index encoding.
Comments suppressed due to low confidence (2)

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:554

  • RuntimeAsyncStackState contains managed reference fields, but this local is left uninitialized before its address is stored in TLS (awaitState.Push(&stackState)). This can expose garbage references to the GC (and Push only initializes a subset of fields), risking GC crashes/corruption. Initialize stackState to default (or otherwise fully clear all reference fields before any GC safepoint) before calling Push.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:655

  • Same issue as in DispatchContinuations: RuntimeAsyncStackState stackState; is uninitialized even though the struct contains managed references and its address is pushed into TLS via awaitState.Push(&stackState). This can leave garbage object references visible to the GC until fields are explicitly set. Ensure stackState is zero-initialized (e.g., = default) or otherwise cleared before pushing.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

CopilotAI review requested due to automatic review settings April 29, 2026 09:11

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • InterpAsyncSuspendData.restoreExecutionContextMethod is still populated, but after removing the interpreter-side RestoreExecutionContext call there don’t appear to be any remaining reads of this field. Consider removing the field from InterpAsyncSuspendData (and this assignment) to reduce per-suspension metadata size and avoid dead state.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

CopilotAI review requested due to automatic review settings April 30, 2026 11:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • CORINFO_ASYNC_INFO no longer exposes restoreExecutionContextMethHnd, but the interpreter still stores asyncInfo.restoreExecutionContextMethHnd into InterpAsyncSuspendData. This will fail to compile and should be removed/rewired now that execution context restoration is done by the dispatcher.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

Comment threadsrc/coreclr/inc/corinfo.h
Comment threadsrc/coreclr/vm/corelib.h
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Comment threadsrc/coreclr/interpreter/inc/interpretershared.h
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Comment threadsrc/coreclr/jit/async.cpp
Comment threadsrc/coreclr/jit/fgbasic.cpp
CopilotAI review requested due to automatic review settings April 30, 2026 12:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 30, 2026 12:38

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/interpexec.cpp

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @VSadov (async) @AndyAyersMS (JIT) @davidwrighton /@janvorli (interpreter)

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT changes look good.

Comment threadsrc/coreclr/jit/fgbasic.cpp

@VSadovVSadov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Will merge this, @janvorli@davidwrighton let me know if you have any comments on the interpreter change and I can address it in a follow-up.

@jakobbotsch
jakobbotsch merged commit 83ebc00 into dotnet:mainMay 4, 2026
124 checks passed
@jakobbotsch
jakobbotsch deleted the restore-execution-context-in-dispatcher branch May 4, 2026 11:06
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@VSadov@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code - #127511

Merged
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher
May 4, 2026
Merged

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code#127511
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 28, 2026

Copy link
Copy Markdown
Member

Remove RestoreExecutionContext call from JIT resumption code and from the interpreter. Instead encode the ExecutionContext's location in the continuation and let the dispatcher restore it. This removes a TLS access + helper call from the resumption path (avoiding the TLS and inlining the helper call in the dispatcher).

Improves suspension/resumption performance by about 7-8% and is also a good size improvement. Removing the call from the resumption path allows keeping the continuation in a volatile register, which also helps register allocation in a number of cases.

Diffs before JIT-EE GUID update

Micro benchmark with warmup
usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceAsyncMicro;publicclassProgram{staticvoidMain(){NullAwaiterna=newNullAwaiter();for(inti=0;i<10;i++){for(intj=0;j<100;j++){Taskt=Foo(100,na);while(!t.IsCompleted){na.Continue();}}Thread.Sleep(100);}for(inti=0;i<50;i++){Taskt=Foo(10_000_000,na);while(!t.IsCompleted){na.Continue();}}}staticints_value;staticasyncTaskFoo(intn,NullAwaiterna){for(inti=0;i<n;i++){s_value+=i;}Stopwatchtimer=Stopwatch.StartNew();for(inti=0;i<n;i++){awaitna;}if(n>100)Console.WriteLine("Took {0:F1} ms",timer.Elapsed.TotalMilliseconds);}privateclassNullAwaiter:ICriticalNotifyCompletion{publicActionContinue;publicNullAwaiterGetAwaiter()=>this;publicboolIsCompleted=>false;publicvoidGetResult(){}publicvoidUnsafeOnCompleted(Actioncontinuation){Continue=continuation;}publicvoidOnCompleted(Actioncontinuation){thrownewNotImplementedException();}}}

About 7-8% improvement:

-Took 268.5 ms-Took 265.9 ms-Took 267.9 ms-Took 270.0 ms-Took 269.4 ms+Took 249.4 ms+Took 248.3 ms+Took 250.3 ms+Took 249.2 ms+Took 248.9 ms
NativeAOT test sizes
BaseSizeDiffSizeDeltaPercentName
31,037,44030,944,256-93,184-0.300%System.Net.Http.Functional.Tests.exe
16,847,87216,803,328-44,544-0.264%System.Linq.AsyncEnumerable.Tests.exe
115,269,120115,089,408-179,712-0.156%System.Text.Json.SourceGeneration.Roslyn4.4.Tests.exe
20,942,33620,912,640-29,696-0.142%System.Net.Quic.Functional.Tests.exe
20,033,02420,005,376-27,648-0.138%System.Formats.Tar.Tests.exe
19,558,91219,533,824-25,088-0.128%System.IO.Compression.Tests.exe
10,055,16810,042,880-12,288-0.122%System.IO.Compression.ZipFile.Tests.exe
14,901,76014,883,840-17,920-0.120%System.Xml.Linq.Streaming.Tests.exe
16,778,75216,758,784-19,968-0.119%System.Xml.Linq.Misc.Tests.exe
28,789,76028,757,504-32,256-0.112%System.Net.Http.WinHttpHandler.Functional.Tests.exe
16,516,60816,498,176-18,432-0.112%System.Xml.Linq.Events.Tests.exe
17,065,47217,046,528-18,944-0.111%System.Xml.Linq.xNodeBuilder.Tests.exe
22,732,80022,708,224-24,576-0.108%System.Net.Sockets.Tests.exe
16,671,74416,653,824-17,920-0.107%System.Xml.Linq.Properties.Tests.exe
17,123,84017,105,920-17,920-0.105%System.Xml.Linq.TreeManipulation.Tests.exe
17,007,61616,989,696-17,920-0.105%System.Xml.Linq.xNodeReader.Tests.exe
20,003,84019,982,848-20,992-0.105%System.Net.WebSockets.Client.Tests.exe
19,053,05619,034,112-18,944-0.099%System.Net.HttpListener.Tests.exe
10,660,86410,650,624-10,240-0.096%System.IO.Pipelines.Tests.exe
20,267,00820,248,064-18,944-0.093%System.Threading.Tasks.Dataflow.Tests.exe
17,728,51217,713,664-14,848-0.084%System.Threading.Tasks.Extensions.Tests.exe
14,569,47214,557,696-11,776-0.081%System.Net.WebClient.Tests.exe
11,992,06411,982,336-9,728-0.081%System.IO.Tests.exe
21,089,79221,072,896-16,896-0.080%System.Net.Requests.Tests.exe
21,708,80021,691,392-17,408-0.080%System.IO.FileSystem.Tests.exe
10,278,91210,270,720-8,192-0.080%System.Threading.Channels.Tests.exe
27,894,27227,874,304-19,968-0.072%System.Net.Security.Tests.exe
18,447,87218,434,560-13,312-0.072%System.Threading.Tasks.Parallel.Tests.exe
13,242,36813,233,152-9,216-0.070%System.IO.Packaging.Tests.exe
9,731,0729,724,416-6,656-0.068%System.Threading.RateLimiting.Tests.exe
33,165,31233,142,784-22,528-0.068%System.Private.Xml.Tests.exe
13,869,05613,859,840-9,216-0.066%Microsoft.Extensions.Configuration.Functional.Tests.exe
19,545,60019,532,800-12,800-0.065%System.Diagnostics.Process.Tests.exe
12,849,66412,841,472-8,192-0.064%System.Xml.Schema.Extensions.Tests.exe
12,416,00012,408,320-7,680-0.062%System.Xml.Linq.SDMSample.Tests.exe
17,431,55217,420,800-10,752-0.062%System.Net.Ping.Functional.Tests.exe
20,540,41620,527,616-12,800-0.062%System.Threading.Tasks.Tests.exe
15,759,87215,750,144-9,728-0.062%System.Windows.Extensions.Tests.exe
10,056,19210,050,048-6,144-0.061%System.Net.ServerSentEvents.Tests.exe
15,102,46415,093,248-9,216-0.061%System.Drawing.Primitives.Tests.exe
17,571,84017,561,088-10,752-0.061%MetricOuterLoop1.Tests.exe
17,566,72017,555,968-10,752-0.061%MetricOuterLoop.Tests.exe
19,289,60019,277,824-11,776-0.061%System.IO.Pipes.Tests.exe
17,791,48817,780,736-10,752-0.060%System.Formats.Tar.Manual.Tests.exe
17,967,61617,956,864-10,752-0.060%System.Threading.ThreadPool.WindowsThreadPool.Tests.exe
17,329,15217,318,912-10,240-0.059%System.Threading.Timer.Tests.exe
14,130,17614,121,984-8,192-0.058%System.DirectoryServices.Protocols.Tests.exe
17,616,89617,606,656-10,240-0.058%System.Threading.Thread.Tests.exe
19,681,79219,670,528-11,264-0.057%System.Net.Http.Unit.Tests.exe
17,160,19217,150,464-9,728-0.057%System.Runtime.Serialization.Formatters.Disabled.Tests.exe
17,967,10417,956,864-10,240-0.057%System.Threading.ThreadPool.Tests.exe
19,870,72019,859,456-11,264-0.057%System.Text.Encoding.Tests.exe
18,774,01618,763,264-10,752-0.057%Microsoft.Extensions.FileProviders.Physical.Tests.exe
27,160,06427,144,704-15,360-0.057%Microsoft.Extensions.Hosting.Unit.Tests.exe
17,214,97617,205,248-9,728-0.057%System.Net.ServicePoint.Tests.exe
17,312,76817,303,040-9,728-0.056%System.Security.Principal.Windows.Tests.exe
17,230,84817,221,120-9,728-0.056%System.ComponentModel.EventBasedAsync.Tests.exe
18,128,89618,118,656-10,240-0.056%System.Diagnostics.TextWriterTraceListener.Tests.exe
17,298,94417,289,216-9,728-0.056%System.Security.Claims.Tests.exe
17,431,04017,421,312-9,728-0.056%System.Diagnostics.TraceSource.Tests.exe
17,282,04817,272,320-9,728-0.056%System.Threading.Overlapped.Tests.exe
18,177,53618,167,296-10,240-0.056%System.Text.Encoding.CodePages.Tests.exe
17,356,28817,346,560-9,728-0.056%Microsoft.Win32.SystemEvents.Tests.exe
18,586,62418,576,384-10,240-0.055%ComInterfaceGenerator.Tests.exe
17,661,44017,651,712-9,728-0.055%System.IO.FileSystem.Watcher.Tests.exe
9,251,8409,246,720-5,120-0.055%Microsoft.Bcl.AsyncInterfaces.Tests.exe
13,941,24813,933,568-7,680-0.055%Microsoft.Extensions.Configuration.Xml.Tests.exe
18,492,92818,482,688-10,240-0.055%Microsoft.Extensions.Configuration.Tests.exe
17,662,97617,653,248-9,728-0.055%System.Buffers.Tests.exe
18,489,34418,479,104-10,240-0.055%Microsoft.Extensions.Hosting.Systemd.Tests.exe
15,080,44815,072,256-8,192-0.054%System.Security.Cryptography.Cng.Tests.exe
17,154,04817,144,832-9,216-0.054%IcuAppLocal.Tests.exe
15,039,48815,031,296-8,192-0.054%System.Data.DataSetExtensions.Tests.exe
18,062,33618,052,608-9,728-0.054%System.Console.Tests.exe
17,288,19217,278,976-9,216-0.053%System.Runtime.InteropServices.RuntimeInformation.Tests.exe
17,361,40817,352,192-9,216-0.053%System.Diagnostics.StackTrace.Tests.exe
18,455,55218,445,824-9,728-0.053%Microsoft.Extensions.Configuration.FileExtensions.Tests.exe
17,235,96817,226,752-9,216-0.053%System.Runtime.InvariantTimezone.Tests.exe
18,518,01618,508,288-9,728-0.053%System.IO.MemoryMappedFiles.Tests.exe
18,693,63218,683,904-9,728-0.052%Microsoft.Extensions.Logging.Console.Tests.exe
18,032,12818,022,912-9,216-0.051%Microsoft.Extensions.Diagnostics.Tests.exe
16,107,00816,098,816-8,192-0.051%System.Data.Odbc.Tests.exe
24,284,67224,272,384-12,288-0.051%Microsoft.Extensions.Http.Tests.exe
20,532,73620,522,496-10,240-0.050%System.Runtime.Extensions.Tests.exe
18,371,58418,362,368-9,216-0.050%System.Threading.Tests.exe
18,356,73618,347,520-9,216-0.050%Microsoft.Extensions.FileProviders.Composite.Tests.exe
18,381,82418,372,608-9,216-0.050%Microsoft.Extensions.Primitives.Tests.exe
11,331,07211,325,440-5,632-0.050%System.Net.WebSockets.Tests.exe
19,295,74419,286,016-9,728-0.050%System.Net.Primitives.Functional.Tests.exe
19,972,60819,962,880-9,728-0.049%Microsoft.Extensions.Logging.Tests.exe
11,588,09611,582,464-5,632-0.049%System.Net.Http.Json.Unit.Tests.exe
19,744,76819,735,040-9,728-0.049%System.Resources.ResourceManager.Tests.exe
9,334,7849,330,176-4,608-0.049%Microsoft.Extensions.Diagnostics.Abstractions.Tests.exe
18,833,92018,824,704-9,216-0.049%System.Runtime.Caching.Tests.exe
19,080,19219,070,976-9,216-0.048%Microsoft.Extensions.Hosting.WindowsServices.Tests.exe
9,660,4169,655,808-4,608-0.048%Microsoft.Extensions.Hosting.Functional.Tests.exe
20,475,90420,466,176-9,728-0.048%System.Diagnostics.DiagnosticSource.Tests.exe
20,741,63220,731,904-9,728-0.047%System.Collections.Concurrent.Tests.exe
10,106,36810,101,760-4,608-0.046%Microsoft.Extensions.Caching.Memory.Tests.exe
20,234,75220,225,536-9,216-0.046%System.Runtime.InteropServices.Tests.exe
20,454,91220,445,696-9,216-0.045%System.Reflection.Tests.exe
19,486,20819,477,504-8,704-0.045%Microsoft.Extensions.Configuration.UserSecrets.Tests.exe
11,274,24011,269,120-5,120-0.045%System.IO.Compression.Brotli.Tests.exe
19,555,84019,547,136-8,704-0.045%Microsoft.Extensions.Configuration.Json.Tests.exe
23,405,05623,394,816-10,240-0.044%System.Memory.Tests.exe
25,891,32825,880,064-11,264-0.044%System.Text.Json.SourceGeneration.Roslyn3.11.Tests.exe
10,510,33610,505,728-4,608-0.044%Microsoft.Extensions.Options.Tests.exe
9,442,8169,438,720-4,096-0.043%Microsoft.Extensions.Logging.Testing.Tests.exe
26,440,70426,429,440-11,264-0.043%System.ComponentModel.TypeConverter.Tests.exe
21,622,78421,613,568-9,216-0.043%System.Data.OleDb.Tests.exe
26,006,52825,996,288-10,240-0.039%System.Globalization.Nls.Tests.exe
20,808,70420,801,024-7,680-0.037%System.Security.Cryptography.Csp.Tests.exe
29,403,13629,392,384-10,752-0.037%Microsoft.Extensions.DependencyModel.Tests.exe
26,095,61626,085,888-9,728-0.037%System.Globalization.Tests.exe
21,072,38421,064,704-7,680-0.036%Microsoft.Extensions.Logging.EventSource.Tests.exe
45,486,08045,470,208-15,872-0.035%System.Security.Cryptography.Tests.exe
32,739,84032,730,112-9,728-0.030%System.Linq.Expressions.Tests.exe
33,385,98433,376,256-9,728-0.029%Microsoft.Bcl.Cryptography.Tests.exe
44,704,76844,693,504-11,264-0.025%System.Runtime.Tests.exe
2,233,3442,232,832-512-0.023%clrjit.dll
10,494,46410,492,928-1,536-0.015%System.Net.Http.WinHttpHandler.Unit.Tests.exe
10,586,11210,584,576-1,536-0.015%Common.Tests.exe
9,026,0489,025,024-1,024-0.011%Microsoft.Extensions.FileSystemGlobbing.Tests.exe
9,347,5849,346,560-1,024-0.011%System.Security.Permissions.Tests.exe
9,612,8009,611,776-1,024-0.011%System.Diagnostics.EventLog.Tests.exe
12,185,08812,184,064-1,024-0.008%System.Net.NetworkInformation.Functional.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Nls.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Tests.exe
8,743,9368,743,424-512-0.006%Invariant.Tests.exe
8,975,8728,975,360-512-0.006%System.Net.Primitives.Pal.Tests.exe
8,798,2088,797,696-512-0.006%System.Resources.Reader.Tests.exe
8,667,1368,666,624-512-0.006%System.Runtime.CompilerServices.Unsafe.Tests.exe
8,916,4808,915,968-512-0.006%System.IO.Pipes.AccessControl.Tests.exe
9,027,0729,026,560-512-0.006%System.Net.NameResolution.Pal.Tests.exe
9,191,9369,191,424-512-0.006%Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.exe
8,763,9048,763,392-512-0.006%Microsoft.Bcl.TimeProvider.Tests.exe
8,609,7928,609,280-512-0.006%System.Composition.Runtime.Tests.exe
9,129,4729,128,960-512-0.006%System.Security.AccessControl.Tests.exe
8,803,3288,802,816-512-0.006%System.Web.HttpUtility.Tests.exe
9,041,9209,041,408-512-0.006%Microsoft.Extensions.Configuration.CommandLine.Tests.exe
8,638,4648,637,952-512-0.006%System.Globalization.CalendarsWithConfigSwitch.Tests.exe
8,533,5048,532,992-512-0.006%System.ComponentModel.Tests.exe
8,686,5928,686,080-512-0.006%System.Security.Cryptography.ProtectedData.Tests.exe
8,755,7128,755,200-512-0.006%System.IO.FileSystem.DriveInfo.Tests.exe
8,977,4088,976,896-512-0.006%Microsoft.Win32.Registry.Tests.exe
8,685,5688,685,056-512-0.006%System.IO.FileSystem.Manual.Tests.exe
9,095,6809,095,168-512-0.006%System.IO.FileSystem.AccessControl.Tests.exe
10,048,51210,048,000-512-0.005%System.Diagnostics.Debug.Tests.exe
11,179,52011,179,008-512-0.005%System.Text.Encodings.Web.Tests.exe
11,034,11211,033,600-512-0.005%System.Runtime.Numerics.Tests.exe
11,363,32811,362,816-512-0.005%System.Net.Security.Unit.Tests.exe
9,337,3449,336,832-512-0.005%System.IO.IsolatedStorage.Tests.exe
9,748,9929,749,504+512+0.005%System.Formats.Asn1.Tests.exe
9,473,5369,473,024-512-0.005%Microsoft.Extensions.Configuration.Ini.Tests.exe
10,936,32010,935,808-512-0.005%System.Runtime.Intrinsics.Tests.exe
9,571,3289,570,816-512-0.005%System.Memory.Data.Tests.exe
9,660,9289,660,416-512-0.005%System.IO.UnmanagedMemoryStream.Tests.exe
9,524,7369,524,224-512-0.005%System.IO.Hashing.Tests.exe
9,361,9209,361,408-512-0.005%System.Net.Mail.Unit.Tests.exe
11,590,14411,589,632-512-0.004%System.Resources.Extensions.Tests.exe
11,469,31211,468,800-512-0.004%System.IO.Ports.Tests.exe
11,779,07211,778,560-512-0.004%System.Security.Cryptography.Cose.Tests.exe
17,824,76817,824,256-512-0.003%System.Collections.Tests.exe
18,770,43218,770,944+512+0.003%System.Numerics.Vectors.Tests.exe
22,320,64022,320,128-512-0.002%System.Security.Cryptography.Pkcs.Tests.exe
8,988,6728,988,67200.000%System.Runtime.Serialization.Primitives.Tests.exe
8,690,1768,690,17600.000%System.Security.SecureString.Tests.exe
9,201,6649,201,66400.000%System.ServiceProcess.ServiceController.Tests.exe
7,318,0167,318,01600.000%XUnitLogChecker.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
84,48084,48000.000%System.Globalization.Native.dll
108,032108,03200.000%CMakeCXXCompilerId.exe
108,032108,03200.000%CMakeCCompilerId.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
8,673,2808,673,28000.000%System.Runtime.InteropServices.ComDisabled.Tests.exe
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,608,7688,608,76800.000%System.Xml.Linq.Axes.Tests.exe
9,069,0569,069,05600.000%System.ValueTuple.Tests.exe
8,945,1528,945,15200.000%System.Threading.AccessControl.Tests.exe
9,690,1129,690,11200.000%System.Text.RegularExpressions.Unit.Tests.exe
8,543,2328,543,23200.000%System.Text.Encoding.Extensions.Tests.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
536,096536,09600.000%msquic.dll
8,529,4088,529,40800.000%System.IO.FileSystem.Primitives.Tests.exe
8,532,4808,532,48000.000%System.Runtime.CompilerServices.VisualC.Tests.exe
536,096536,09600.000%msquic.dll
1,308,6721,308,67200.000%mscordbi.dll
1,501,6961,501,69600.000%mscordaccore.dll
1,501,6961,501,69600.000%mscordaccore_amd64_amd64_42.42.42.42424.dll
361,984361,98400.000%hostpolicy.dll
350,208350,20800.000%hostfxr.dll
62,46462,46400.000%createdump.exe
210,944210,94400.000%corerun.exe
4,955,6484,955,64800.000%coreclr.dll
722,944722,94400.000%clrgcexp.dll
678,400678,40000.000%clrgc.dll
307,200307,20000.000%clretwrc.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
84,48084,48000.000%System.Globalization.Native.dll
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
696,320696,32000.000%FileCheck.exe
9,956,3529,956,35200.000%llvm-mca.exe
13,419,52013,419,52000.000%crossgen2.exe
7,703,0407,703,04000.000%ilasm.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
15,940,09615,940,09600.000%ilc.exe
8,938,4968,938,49600.000%Microsoft.Bcl.Memory.Tests.exe
8,578,0488,578,04800.000%Microsoft.Bcl.Numerics.Tests.exe
8,587,2648,587,26400.000%Microsoft.Extensions.Hosting.Abstractions.Tests.exe
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
9,947,6489,947,64800.000%LibraryImportGenerator.Tests.exe
8,655,8728,655,87200.000%System.Runtime.Handles.Tests.exe
16,973,82416,973,82400.000%System.Private.CoreLib.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
8,591,3608,591,36000.000%System.Resources.Writer.Tests.exe
9,011,2009,011,20000.000%System.Reflection.TypeExtensions.Tests.exe
12,271,10412,271,10400.000%System.Reflection.Metadata.Tests.exe
8,849,9208,849,92000.000%System.Reflection.Extensions.Tests.exe
9,350,6569,350,65600.000%System.Reflection.Context.Tests.exe
8,704,5128,704,51200.000%System.Private.Uri.Unit.Tests.exe
9,631,7449,631,74400.000%System.Private.Uri.Functional.Tests.exe
9,785,8569,785,85600.000%System.Net.WebProxy.Tests.exe
8,627,2008,627,20000.000%System.Net.WebHeaderCollection.Tests.exe
9,300,9929,300,99200.000%System.Net.Primitives.UnitTests.Tests.exe
15,486,97615,486,97600.000%System.Linq.Tests.exe
696,320696,32000.000%FileCheck.exe
9,150,9769,150,97600.000%System.Globalization.Calendars.Tests.exe
9,837,5689,837,56800.000%System.Formats.Nrbf.Tests.exe
8,534,5288,534,52800.000%System.Diagnostics.Tools.Tests.exe
8,702,4648,702,46400.000%System.Diagnostics.FileVersionInfo.Tests.exe
8,547,8408,547,84000.000%System.Diagnostics.Contracts.Tests.exe
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,649,2168,649,21600.000%Microsoft.Win32.Primitives.Tests.exe
9,934,3369,934,33600.000%System.Collections.NonGeneric.Tests.exe
9,734,6569,734,65600.000%System.Collections.Specialized.Tests.exe
9,147,3929,147,39200.000%System.ComponentModel.Primitives.Tests.exe
8,544,7688,544,76800.000%System.Composition.AttributeModel.Tests.exe
9,615,8729,615,87200.000%System.Composition.Convention.Tests.exe
8,821,7608,821,76000.000%System.Console.Manual.Tests.exe
8,632,8328,632,83200.000%Microsoft.Win32.Registry.AccessControl.Tests.exe
9,956,3529,956,35200.000%llvm-mca.exe

Remove `RestoreExecutionContext` call from JIT resumption code and from
the interpreter. Instead encode the `ExecutionContext`'s location in the
continuation and let the dispatcher restore it. This removes a TLS
access + helper call from the resumption path (avoiding the TLS and
inlining the helper call in the dispatcher).
Improves suspension/resumption performance by about 5-6% and should also
be a small size improvement.
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes CoreCLR runtime-async suspension/resumption so the dispatcher (managed AsyncHelpers) restores ExecutionContext, instead of having interpreter/JIT resumption stubs call a restore helper. The continuation’s flags now encode the ExecutionContext storage slot, enabling the dispatcher to restore without an extra TLS lookup + helper call on the hot resumption path.

Changes:

  • Add continuation support for locating/storing the ExecutionContext via encoded indices in continuation flags (VM + managed + JIT + interpreter).
  • Remove RestoreExecutionContext calls from interpreter and JIT resumption code; add restoration to the dispatcher loop.
  • Preserve BBF_ASYNC_RESUMPTION across certain flow optimizations that may bypass resumption stubs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/vm/object.hAdds VM helper to locate ExecutionContext storage in a continuation via encoded flag bits.
src/coreclr/vm/interpexec.cppWrites captured ExecutionContext via the encoded slot; removes interpreter-side restore on resume.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.csMoves ExecutionContext restore into dispatcher; adjusts flag layout and RestoreExecutionContext signature to avoid TLS lookup.
src/coreclr/jit/fgopt.cppCopies BBF_ASYNC_RESUMPTION during certain jump/switch/flow optimizations to preserve async side-entry affordances.
src/coreclr/jit/async.cppUpdates continuation layout/flag encoding for ExecutionContext; removes JIT-side restore on resumption.
src/coreclr/interpreter/inc/interpretershared.hRemoves interpreter suspend-data field that stored a raw execution-context offset.
src/coreclr/interpreter/compiler.cppEncodes ExecutionContext slot in flags and updates interpreter continuation layout accordingly.
src/coreclr/inc/corinfo.hUpdates CorInfoContinuationFlags bit assignments to include ExecutionContext index encoding.
Comments suppressed due to low confidence (2)

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:554

  • RuntimeAsyncStackState contains managed reference fields, but this local is left uninitialized before its address is stored in TLS (awaitState.Push(&stackState)). This can expose garbage references to the GC (and Push only initializes a subset of fields), risking GC crashes/corruption. Initialize stackState to default (or otherwise fully clear all reference fields before any GC safepoint) before calling Push.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:655

  • Same issue as in DispatchContinuations: RuntimeAsyncStackState stackState; is uninitialized even though the struct contains managed references and its address is pushed into TLS via awaitState.Push(&stackState). This can leave garbage object references visible to the GC until fields are explicitly set. Ensure stackState is zero-initialized (e.g., = default) or otherwise cleared before pushing.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

CopilotAI review requested due to automatic review settings April 29, 2026 09:11

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • InterpAsyncSuspendData.restoreExecutionContextMethod is still populated, but after removing the interpreter-side RestoreExecutionContext call there don’t appear to be any remaining reads of this field. Consider removing the field from InterpAsyncSuspendData (and this assignment) to reduce per-suspension metadata size and avoid dead state.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

CopilotAI review requested due to automatic review settings April 30, 2026 11:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • CORINFO_ASYNC_INFO no longer exposes restoreExecutionContextMethHnd, but the interpreter still stores asyncInfo.restoreExecutionContextMethHnd into InterpAsyncSuspendData. This will fail to compile and should be removed/rewired now that execution context restoration is done by the dispatcher.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

Comment threadsrc/coreclr/inc/corinfo.h
Comment threadsrc/coreclr/vm/corelib.h
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Comment threadsrc/coreclr/interpreter/inc/interpretershared.h
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Comment threadsrc/coreclr/jit/async.cpp
Comment threadsrc/coreclr/jit/fgbasic.cpp
CopilotAI review requested due to automatic review settings April 30, 2026 12:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 30, 2026 12:38

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/interpexec.cpp

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @VSadov (async) @AndyAyersMS (JIT) @davidwrighton /@janvorli (interpreter)

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT changes look good.

Comment threadsrc/coreclr/jit/fgbasic.cpp

@VSadovVSadov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Will merge this, @janvorli@davidwrighton let me know if you have any comments on the interpreter change and I can address it in a follow-up.

@jakobbotsch
jakobbotsch merged commit 83ebc00 into dotnet:mainMay 4, 2026
124 checks passed
@jakobbotsch
jakobbotsch deleted the restore-execution-context-in-dispatcher branch May 4, 2026 11:06
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@VSadov@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code - #127511

Merged
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher
May 4, 2026
Merged

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code#127511
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 28, 2026

Copy link
Copy Markdown
Member

Remove RestoreExecutionContext call from JIT resumption code and from the interpreter. Instead encode the ExecutionContext's location in the continuation and let the dispatcher restore it. This removes a TLS access + helper call from the resumption path (avoiding the TLS and inlining the helper call in the dispatcher).

Improves suspension/resumption performance by about 7-8% and is also a good size improvement. Removing the call from the resumption path allows keeping the continuation in a volatile register, which also helps register allocation in a number of cases.

Diffs before JIT-EE GUID update

Micro benchmark with warmup
usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceAsyncMicro;publicclassProgram{staticvoidMain(){NullAwaiterna=newNullAwaiter();for(inti=0;i<10;i++){for(intj=0;j<100;j++){Taskt=Foo(100,na);while(!t.IsCompleted){na.Continue();}}Thread.Sleep(100);}for(inti=0;i<50;i++){Taskt=Foo(10_000_000,na);while(!t.IsCompleted){na.Continue();}}}staticints_value;staticasyncTaskFoo(intn,NullAwaiterna){for(inti=0;i<n;i++){s_value+=i;}Stopwatchtimer=Stopwatch.StartNew();for(inti=0;i<n;i++){awaitna;}if(n>100)Console.WriteLine("Took {0:F1} ms",timer.Elapsed.TotalMilliseconds);}privateclassNullAwaiter:ICriticalNotifyCompletion{publicActionContinue;publicNullAwaiterGetAwaiter()=>this;publicboolIsCompleted=>false;publicvoidGetResult(){}publicvoidUnsafeOnCompleted(Actioncontinuation){Continue=continuation;}publicvoidOnCompleted(Actioncontinuation){thrownewNotImplementedException();}}}

About 7-8% improvement:

-Took 268.5 ms-Took 265.9 ms-Took 267.9 ms-Took 270.0 ms-Took 269.4 ms+Took 249.4 ms+Took 248.3 ms+Took 250.3 ms+Took 249.2 ms+Took 248.9 ms
NativeAOT test sizes
BaseSizeDiffSizeDeltaPercentName
31,037,44030,944,256-93,184-0.300%System.Net.Http.Functional.Tests.exe
16,847,87216,803,328-44,544-0.264%System.Linq.AsyncEnumerable.Tests.exe
115,269,120115,089,408-179,712-0.156%System.Text.Json.SourceGeneration.Roslyn4.4.Tests.exe
20,942,33620,912,640-29,696-0.142%System.Net.Quic.Functional.Tests.exe
20,033,02420,005,376-27,648-0.138%System.Formats.Tar.Tests.exe
19,558,91219,533,824-25,088-0.128%System.IO.Compression.Tests.exe
10,055,16810,042,880-12,288-0.122%System.IO.Compression.ZipFile.Tests.exe
14,901,76014,883,840-17,920-0.120%System.Xml.Linq.Streaming.Tests.exe
16,778,75216,758,784-19,968-0.119%System.Xml.Linq.Misc.Tests.exe
28,789,76028,757,504-32,256-0.112%System.Net.Http.WinHttpHandler.Functional.Tests.exe
16,516,60816,498,176-18,432-0.112%System.Xml.Linq.Events.Tests.exe
17,065,47217,046,528-18,944-0.111%System.Xml.Linq.xNodeBuilder.Tests.exe
22,732,80022,708,224-24,576-0.108%System.Net.Sockets.Tests.exe
16,671,74416,653,824-17,920-0.107%System.Xml.Linq.Properties.Tests.exe
17,123,84017,105,920-17,920-0.105%System.Xml.Linq.TreeManipulation.Tests.exe
17,007,61616,989,696-17,920-0.105%System.Xml.Linq.xNodeReader.Tests.exe
20,003,84019,982,848-20,992-0.105%System.Net.WebSockets.Client.Tests.exe
19,053,05619,034,112-18,944-0.099%System.Net.HttpListener.Tests.exe
10,660,86410,650,624-10,240-0.096%System.IO.Pipelines.Tests.exe
20,267,00820,248,064-18,944-0.093%System.Threading.Tasks.Dataflow.Tests.exe
17,728,51217,713,664-14,848-0.084%System.Threading.Tasks.Extensions.Tests.exe
14,569,47214,557,696-11,776-0.081%System.Net.WebClient.Tests.exe
11,992,06411,982,336-9,728-0.081%System.IO.Tests.exe
21,089,79221,072,896-16,896-0.080%System.Net.Requests.Tests.exe
21,708,80021,691,392-17,408-0.080%System.IO.FileSystem.Tests.exe
10,278,91210,270,720-8,192-0.080%System.Threading.Channels.Tests.exe
27,894,27227,874,304-19,968-0.072%System.Net.Security.Tests.exe
18,447,87218,434,560-13,312-0.072%System.Threading.Tasks.Parallel.Tests.exe
13,242,36813,233,152-9,216-0.070%System.IO.Packaging.Tests.exe
9,731,0729,724,416-6,656-0.068%System.Threading.RateLimiting.Tests.exe
33,165,31233,142,784-22,528-0.068%System.Private.Xml.Tests.exe
13,869,05613,859,840-9,216-0.066%Microsoft.Extensions.Configuration.Functional.Tests.exe
19,545,60019,532,800-12,800-0.065%System.Diagnostics.Process.Tests.exe
12,849,66412,841,472-8,192-0.064%System.Xml.Schema.Extensions.Tests.exe
12,416,00012,408,320-7,680-0.062%System.Xml.Linq.SDMSample.Tests.exe
17,431,55217,420,800-10,752-0.062%System.Net.Ping.Functional.Tests.exe
20,540,41620,527,616-12,800-0.062%System.Threading.Tasks.Tests.exe
15,759,87215,750,144-9,728-0.062%System.Windows.Extensions.Tests.exe
10,056,19210,050,048-6,144-0.061%System.Net.ServerSentEvents.Tests.exe
15,102,46415,093,248-9,216-0.061%System.Drawing.Primitives.Tests.exe
17,571,84017,561,088-10,752-0.061%MetricOuterLoop1.Tests.exe
17,566,72017,555,968-10,752-0.061%MetricOuterLoop.Tests.exe
19,289,60019,277,824-11,776-0.061%System.IO.Pipes.Tests.exe
17,791,48817,780,736-10,752-0.060%System.Formats.Tar.Manual.Tests.exe
17,967,61617,956,864-10,752-0.060%System.Threading.ThreadPool.WindowsThreadPool.Tests.exe
17,329,15217,318,912-10,240-0.059%System.Threading.Timer.Tests.exe
14,130,17614,121,984-8,192-0.058%System.DirectoryServices.Protocols.Tests.exe
17,616,89617,606,656-10,240-0.058%System.Threading.Thread.Tests.exe
19,681,79219,670,528-11,264-0.057%System.Net.Http.Unit.Tests.exe
17,160,19217,150,464-9,728-0.057%System.Runtime.Serialization.Formatters.Disabled.Tests.exe
17,967,10417,956,864-10,240-0.057%System.Threading.ThreadPool.Tests.exe
19,870,72019,859,456-11,264-0.057%System.Text.Encoding.Tests.exe
18,774,01618,763,264-10,752-0.057%Microsoft.Extensions.FileProviders.Physical.Tests.exe
27,160,06427,144,704-15,360-0.057%Microsoft.Extensions.Hosting.Unit.Tests.exe
17,214,97617,205,248-9,728-0.057%System.Net.ServicePoint.Tests.exe
17,312,76817,303,040-9,728-0.056%System.Security.Principal.Windows.Tests.exe
17,230,84817,221,120-9,728-0.056%System.ComponentModel.EventBasedAsync.Tests.exe
18,128,89618,118,656-10,240-0.056%System.Diagnostics.TextWriterTraceListener.Tests.exe
17,298,94417,289,216-9,728-0.056%System.Security.Claims.Tests.exe
17,431,04017,421,312-9,728-0.056%System.Diagnostics.TraceSource.Tests.exe
17,282,04817,272,320-9,728-0.056%System.Threading.Overlapped.Tests.exe
18,177,53618,167,296-10,240-0.056%System.Text.Encoding.CodePages.Tests.exe
17,356,28817,346,560-9,728-0.056%Microsoft.Win32.SystemEvents.Tests.exe
18,586,62418,576,384-10,240-0.055%ComInterfaceGenerator.Tests.exe
17,661,44017,651,712-9,728-0.055%System.IO.FileSystem.Watcher.Tests.exe
9,251,8409,246,720-5,120-0.055%Microsoft.Bcl.AsyncInterfaces.Tests.exe
13,941,24813,933,568-7,680-0.055%Microsoft.Extensions.Configuration.Xml.Tests.exe
18,492,92818,482,688-10,240-0.055%Microsoft.Extensions.Configuration.Tests.exe
17,662,97617,653,248-9,728-0.055%System.Buffers.Tests.exe
18,489,34418,479,104-10,240-0.055%Microsoft.Extensions.Hosting.Systemd.Tests.exe
15,080,44815,072,256-8,192-0.054%System.Security.Cryptography.Cng.Tests.exe
17,154,04817,144,832-9,216-0.054%IcuAppLocal.Tests.exe
15,039,48815,031,296-8,192-0.054%System.Data.DataSetExtensions.Tests.exe
18,062,33618,052,608-9,728-0.054%System.Console.Tests.exe
17,288,19217,278,976-9,216-0.053%System.Runtime.InteropServices.RuntimeInformation.Tests.exe
17,361,40817,352,192-9,216-0.053%System.Diagnostics.StackTrace.Tests.exe
18,455,55218,445,824-9,728-0.053%Microsoft.Extensions.Configuration.FileExtensions.Tests.exe
17,235,96817,226,752-9,216-0.053%System.Runtime.InvariantTimezone.Tests.exe
18,518,01618,508,288-9,728-0.053%System.IO.MemoryMappedFiles.Tests.exe
18,693,63218,683,904-9,728-0.052%Microsoft.Extensions.Logging.Console.Tests.exe
18,032,12818,022,912-9,216-0.051%Microsoft.Extensions.Diagnostics.Tests.exe
16,107,00816,098,816-8,192-0.051%System.Data.Odbc.Tests.exe
24,284,67224,272,384-12,288-0.051%Microsoft.Extensions.Http.Tests.exe
20,532,73620,522,496-10,240-0.050%System.Runtime.Extensions.Tests.exe
18,371,58418,362,368-9,216-0.050%System.Threading.Tests.exe
18,356,73618,347,520-9,216-0.050%Microsoft.Extensions.FileProviders.Composite.Tests.exe
18,381,82418,372,608-9,216-0.050%Microsoft.Extensions.Primitives.Tests.exe
11,331,07211,325,440-5,632-0.050%System.Net.WebSockets.Tests.exe
19,295,74419,286,016-9,728-0.050%System.Net.Primitives.Functional.Tests.exe
19,972,60819,962,880-9,728-0.049%Microsoft.Extensions.Logging.Tests.exe
11,588,09611,582,464-5,632-0.049%System.Net.Http.Json.Unit.Tests.exe
19,744,76819,735,040-9,728-0.049%System.Resources.ResourceManager.Tests.exe
9,334,7849,330,176-4,608-0.049%Microsoft.Extensions.Diagnostics.Abstractions.Tests.exe
18,833,92018,824,704-9,216-0.049%System.Runtime.Caching.Tests.exe
19,080,19219,070,976-9,216-0.048%Microsoft.Extensions.Hosting.WindowsServices.Tests.exe
9,660,4169,655,808-4,608-0.048%Microsoft.Extensions.Hosting.Functional.Tests.exe
20,475,90420,466,176-9,728-0.048%System.Diagnostics.DiagnosticSource.Tests.exe
20,741,63220,731,904-9,728-0.047%System.Collections.Concurrent.Tests.exe
10,106,36810,101,760-4,608-0.046%Microsoft.Extensions.Caching.Memory.Tests.exe
20,234,75220,225,536-9,216-0.046%System.Runtime.InteropServices.Tests.exe
20,454,91220,445,696-9,216-0.045%System.Reflection.Tests.exe
19,486,20819,477,504-8,704-0.045%Microsoft.Extensions.Configuration.UserSecrets.Tests.exe
11,274,24011,269,120-5,120-0.045%System.IO.Compression.Brotli.Tests.exe
19,555,84019,547,136-8,704-0.045%Microsoft.Extensions.Configuration.Json.Tests.exe
23,405,05623,394,816-10,240-0.044%System.Memory.Tests.exe
25,891,32825,880,064-11,264-0.044%System.Text.Json.SourceGeneration.Roslyn3.11.Tests.exe
10,510,33610,505,728-4,608-0.044%Microsoft.Extensions.Options.Tests.exe
9,442,8169,438,720-4,096-0.043%Microsoft.Extensions.Logging.Testing.Tests.exe
26,440,70426,429,440-11,264-0.043%System.ComponentModel.TypeConverter.Tests.exe
21,622,78421,613,568-9,216-0.043%System.Data.OleDb.Tests.exe
26,006,52825,996,288-10,240-0.039%System.Globalization.Nls.Tests.exe
20,808,70420,801,024-7,680-0.037%System.Security.Cryptography.Csp.Tests.exe
29,403,13629,392,384-10,752-0.037%Microsoft.Extensions.DependencyModel.Tests.exe
26,095,61626,085,888-9,728-0.037%System.Globalization.Tests.exe
21,072,38421,064,704-7,680-0.036%Microsoft.Extensions.Logging.EventSource.Tests.exe
45,486,08045,470,208-15,872-0.035%System.Security.Cryptography.Tests.exe
32,739,84032,730,112-9,728-0.030%System.Linq.Expressions.Tests.exe
33,385,98433,376,256-9,728-0.029%Microsoft.Bcl.Cryptography.Tests.exe
44,704,76844,693,504-11,264-0.025%System.Runtime.Tests.exe
2,233,3442,232,832-512-0.023%clrjit.dll
10,494,46410,492,928-1,536-0.015%System.Net.Http.WinHttpHandler.Unit.Tests.exe
10,586,11210,584,576-1,536-0.015%Common.Tests.exe
9,026,0489,025,024-1,024-0.011%Microsoft.Extensions.FileSystemGlobbing.Tests.exe
9,347,5849,346,560-1,024-0.011%System.Security.Permissions.Tests.exe
9,612,8009,611,776-1,024-0.011%System.Diagnostics.EventLog.Tests.exe
12,185,08812,184,064-1,024-0.008%System.Net.NetworkInformation.Functional.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Nls.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Tests.exe
8,743,9368,743,424-512-0.006%Invariant.Tests.exe
8,975,8728,975,360-512-0.006%System.Net.Primitives.Pal.Tests.exe
8,798,2088,797,696-512-0.006%System.Resources.Reader.Tests.exe
8,667,1368,666,624-512-0.006%System.Runtime.CompilerServices.Unsafe.Tests.exe
8,916,4808,915,968-512-0.006%System.IO.Pipes.AccessControl.Tests.exe
9,027,0729,026,560-512-0.006%System.Net.NameResolution.Pal.Tests.exe
9,191,9369,191,424-512-0.006%Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.exe
8,763,9048,763,392-512-0.006%Microsoft.Bcl.TimeProvider.Tests.exe
8,609,7928,609,280-512-0.006%System.Composition.Runtime.Tests.exe
9,129,4729,128,960-512-0.006%System.Security.AccessControl.Tests.exe
8,803,3288,802,816-512-0.006%System.Web.HttpUtility.Tests.exe
9,041,9209,041,408-512-0.006%Microsoft.Extensions.Configuration.CommandLine.Tests.exe
8,638,4648,637,952-512-0.006%System.Globalization.CalendarsWithConfigSwitch.Tests.exe
8,533,5048,532,992-512-0.006%System.ComponentModel.Tests.exe
8,686,5928,686,080-512-0.006%System.Security.Cryptography.ProtectedData.Tests.exe
8,755,7128,755,200-512-0.006%System.IO.FileSystem.DriveInfo.Tests.exe
8,977,4088,976,896-512-0.006%Microsoft.Win32.Registry.Tests.exe
8,685,5688,685,056-512-0.006%System.IO.FileSystem.Manual.Tests.exe
9,095,6809,095,168-512-0.006%System.IO.FileSystem.AccessControl.Tests.exe
10,048,51210,048,000-512-0.005%System.Diagnostics.Debug.Tests.exe
11,179,52011,179,008-512-0.005%System.Text.Encodings.Web.Tests.exe
11,034,11211,033,600-512-0.005%System.Runtime.Numerics.Tests.exe
11,363,32811,362,816-512-0.005%System.Net.Security.Unit.Tests.exe
9,337,3449,336,832-512-0.005%System.IO.IsolatedStorage.Tests.exe
9,748,9929,749,504+512+0.005%System.Formats.Asn1.Tests.exe
9,473,5369,473,024-512-0.005%Microsoft.Extensions.Configuration.Ini.Tests.exe
10,936,32010,935,808-512-0.005%System.Runtime.Intrinsics.Tests.exe
9,571,3289,570,816-512-0.005%System.Memory.Data.Tests.exe
9,660,9289,660,416-512-0.005%System.IO.UnmanagedMemoryStream.Tests.exe
9,524,7369,524,224-512-0.005%System.IO.Hashing.Tests.exe
9,361,9209,361,408-512-0.005%System.Net.Mail.Unit.Tests.exe
11,590,14411,589,632-512-0.004%System.Resources.Extensions.Tests.exe
11,469,31211,468,800-512-0.004%System.IO.Ports.Tests.exe
11,779,07211,778,560-512-0.004%System.Security.Cryptography.Cose.Tests.exe
17,824,76817,824,256-512-0.003%System.Collections.Tests.exe
18,770,43218,770,944+512+0.003%System.Numerics.Vectors.Tests.exe
22,320,64022,320,128-512-0.002%System.Security.Cryptography.Pkcs.Tests.exe
8,988,6728,988,67200.000%System.Runtime.Serialization.Primitives.Tests.exe
8,690,1768,690,17600.000%System.Security.SecureString.Tests.exe
9,201,6649,201,66400.000%System.ServiceProcess.ServiceController.Tests.exe
7,318,0167,318,01600.000%XUnitLogChecker.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
84,48084,48000.000%System.Globalization.Native.dll
108,032108,03200.000%CMakeCXXCompilerId.exe
108,032108,03200.000%CMakeCCompilerId.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
8,673,2808,673,28000.000%System.Runtime.InteropServices.ComDisabled.Tests.exe
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,608,7688,608,76800.000%System.Xml.Linq.Axes.Tests.exe
9,069,0569,069,05600.000%System.ValueTuple.Tests.exe
8,945,1528,945,15200.000%System.Threading.AccessControl.Tests.exe
9,690,1129,690,11200.000%System.Text.RegularExpressions.Unit.Tests.exe
8,543,2328,543,23200.000%System.Text.Encoding.Extensions.Tests.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
536,096536,09600.000%msquic.dll
8,529,4088,529,40800.000%System.IO.FileSystem.Primitives.Tests.exe
8,532,4808,532,48000.000%System.Runtime.CompilerServices.VisualC.Tests.exe
536,096536,09600.000%msquic.dll
1,308,6721,308,67200.000%mscordbi.dll
1,501,6961,501,69600.000%mscordaccore.dll
1,501,6961,501,69600.000%mscordaccore_amd64_amd64_42.42.42.42424.dll
361,984361,98400.000%hostpolicy.dll
350,208350,20800.000%hostfxr.dll
62,46462,46400.000%createdump.exe
210,944210,94400.000%corerun.exe
4,955,6484,955,64800.000%coreclr.dll
722,944722,94400.000%clrgcexp.dll
678,400678,40000.000%clrgc.dll
307,200307,20000.000%clretwrc.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
84,48084,48000.000%System.Globalization.Native.dll
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
696,320696,32000.000%FileCheck.exe
9,956,3529,956,35200.000%llvm-mca.exe
13,419,52013,419,52000.000%crossgen2.exe
7,703,0407,703,04000.000%ilasm.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
15,940,09615,940,09600.000%ilc.exe
8,938,4968,938,49600.000%Microsoft.Bcl.Memory.Tests.exe
8,578,0488,578,04800.000%Microsoft.Bcl.Numerics.Tests.exe
8,587,2648,587,26400.000%Microsoft.Extensions.Hosting.Abstractions.Tests.exe
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
9,947,6489,947,64800.000%LibraryImportGenerator.Tests.exe
8,655,8728,655,87200.000%System.Runtime.Handles.Tests.exe
16,973,82416,973,82400.000%System.Private.CoreLib.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
8,591,3608,591,36000.000%System.Resources.Writer.Tests.exe
9,011,2009,011,20000.000%System.Reflection.TypeExtensions.Tests.exe
12,271,10412,271,10400.000%System.Reflection.Metadata.Tests.exe
8,849,9208,849,92000.000%System.Reflection.Extensions.Tests.exe
9,350,6569,350,65600.000%System.Reflection.Context.Tests.exe
8,704,5128,704,51200.000%System.Private.Uri.Unit.Tests.exe
9,631,7449,631,74400.000%System.Private.Uri.Functional.Tests.exe
9,785,8569,785,85600.000%System.Net.WebProxy.Tests.exe
8,627,2008,627,20000.000%System.Net.WebHeaderCollection.Tests.exe
9,300,9929,300,99200.000%System.Net.Primitives.UnitTests.Tests.exe
15,486,97615,486,97600.000%System.Linq.Tests.exe
696,320696,32000.000%FileCheck.exe
9,150,9769,150,97600.000%System.Globalization.Calendars.Tests.exe
9,837,5689,837,56800.000%System.Formats.Nrbf.Tests.exe
8,534,5288,534,52800.000%System.Diagnostics.Tools.Tests.exe
8,702,4648,702,46400.000%System.Diagnostics.FileVersionInfo.Tests.exe
8,547,8408,547,84000.000%System.Diagnostics.Contracts.Tests.exe
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,649,2168,649,21600.000%Microsoft.Win32.Primitives.Tests.exe
9,934,3369,934,33600.000%System.Collections.NonGeneric.Tests.exe
9,734,6569,734,65600.000%System.Collections.Specialized.Tests.exe
9,147,3929,147,39200.000%System.ComponentModel.Primitives.Tests.exe
8,544,7688,544,76800.000%System.Composition.AttributeModel.Tests.exe
9,615,8729,615,87200.000%System.Composition.Convention.Tests.exe
8,821,7608,821,76000.000%System.Console.Manual.Tests.exe
8,632,8328,632,83200.000%Microsoft.Win32.Registry.AccessControl.Tests.exe
9,956,3529,956,35200.000%llvm-mca.exe

Remove `RestoreExecutionContext` call from JIT resumption code and from
the interpreter. Instead encode the `ExecutionContext`'s location in the
continuation and let the dispatcher restore it. This removes a TLS
access + helper call from the resumption path (avoiding the TLS and
inlining the helper call in the dispatcher).
Improves suspension/resumption performance by about 5-6% and should also
be a small size improvement.
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes CoreCLR runtime-async suspension/resumption so the dispatcher (managed AsyncHelpers) restores ExecutionContext, instead of having interpreter/JIT resumption stubs call a restore helper. The continuation’s flags now encode the ExecutionContext storage slot, enabling the dispatcher to restore without an extra TLS lookup + helper call on the hot resumption path.

Changes:

  • Add continuation support for locating/storing the ExecutionContext via encoded indices in continuation flags (VM + managed + JIT + interpreter).
  • Remove RestoreExecutionContext calls from interpreter and JIT resumption code; add restoration to the dispatcher loop.
  • Preserve BBF_ASYNC_RESUMPTION across certain flow optimizations that may bypass resumption stubs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/vm/object.hAdds VM helper to locate ExecutionContext storage in a continuation via encoded flag bits.
src/coreclr/vm/interpexec.cppWrites captured ExecutionContext via the encoded slot; removes interpreter-side restore on resume.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.csMoves ExecutionContext restore into dispatcher; adjusts flag layout and RestoreExecutionContext signature to avoid TLS lookup.
src/coreclr/jit/fgopt.cppCopies BBF_ASYNC_RESUMPTION during certain jump/switch/flow optimizations to preserve async side-entry affordances.
src/coreclr/jit/async.cppUpdates continuation layout/flag encoding for ExecutionContext; removes JIT-side restore on resumption.
src/coreclr/interpreter/inc/interpretershared.hRemoves interpreter suspend-data field that stored a raw execution-context offset.
src/coreclr/interpreter/compiler.cppEncodes ExecutionContext slot in flags and updates interpreter continuation layout accordingly.
src/coreclr/inc/corinfo.hUpdates CorInfoContinuationFlags bit assignments to include ExecutionContext index encoding.
Comments suppressed due to low confidence (2)

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:554

  • RuntimeAsyncStackState contains managed reference fields, but this local is left uninitialized before its address is stored in TLS (awaitState.Push(&stackState)). This can expose garbage references to the GC (and Push only initializes a subset of fields), risking GC crashes/corruption. Initialize stackState to default (or otherwise fully clear all reference fields before any GC safepoint) before calling Push.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:655

  • Same issue as in DispatchContinuations: RuntimeAsyncStackState stackState; is uninitialized even though the struct contains managed references and its address is pushed into TLS via awaitState.Push(&stackState). This can leave garbage object references visible to the GC until fields are explicitly set. Ensure stackState is zero-initialized (e.g., = default) or otherwise cleared before pushing.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

CopilotAI review requested due to automatic review settings April 29, 2026 09:11

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • InterpAsyncSuspendData.restoreExecutionContextMethod is still populated, but after removing the interpreter-side RestoreExecutionContext call there don’t appear to be any remaining reads of this field. Consider removing the field from InterpAsyncSuspendData (and this assignment) to reduce per-suspension metadata size and avoid dead state.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

CopilotAI review requested due to automatic review settings April 30, 2026 11:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • CORINFO_ASYNC_INFO no longer exposes restoreExecutionContextMethHnd, but the interpreter still stores asyncInfo.restoreExecutionContextMethHnd into InterpAsyncSuspendData. This will fail to compile and should be removed/rewired now that execution context restoration is done by the dispatcher.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

Comment threadsrc/coreclr/inc/corinfo.h
Comment threadsrc/coreclr/vm/corelib.h
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Comment threadsrc/coreclr/interpreter/inc/interpretershared.h
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Comment threadsrc/coreclr/jit/async.cpp
Comment threadsrc/coreclr/jit/fgbasic.cpp
CopilotAI review requested due to automatic review settings April 30, 2026 12:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 30, 2026 12:38

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/interpexec.cpp

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @VSadov (async) @AndyAyersMS (JIT) @davidwrighton /@janvorli (interpreter)

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT changes look good.

Comment threadsrc/coreclr/jit/fgbasic.cpp

@VSadovVSadov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Will merge this, @janvorli@davidwrighton let me know if you have any comments on the interpreter change and I can address it in a follow-up.

@jakobbotsch
jakobbotsch merged commit 83ebc00 into dotnet:mainMay 4, 2026
124 checks passed
@jakobbotsch
jakobbotsch deleted the restore-execution-context-in-dispatcher branch May 4, 2026 11:06
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@VSadov@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code - #127511

Merged
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher
May 4, 2026
Merged

Restore ExecutionContext from dispatcher instead of from interpreter/JIT'ed code#127511
jakobbotsch merged 11 commits into
dotnet:mainfrom
jakobbotsch:restore-execution-context-in-dispatcher

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 28, 2026

Copy link
Copy Markdown
Member

Remove RestoreExecutionContext call from JIT resumption code and from the interpreter. Instead encode the ExecutionContext's location in the continuation and let the dispatcher restore it. This removes a TLS access + helper call from the resumption path (avoiding the TLS and inlining the helper call in the dispatcher).

Improves suspension/resumption performance by about 7-8% and is also a good size improvement. Removing the call from the resumption path allows keeping the continuation in a volatile register, which also helps register allocation in a number of cases.

Diffs before JIT-EE GUID update

Micro benchmark with warmup
usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.CompilerServices;usingSystem.Threading;usingSystem.Threading.Tasks;namespaceAsyncMicro;publicclassProgram{staticvoidMain(){NullAwaiterna=newNullAwaiter();for(inti=0;i<10;i++){for(intj=0;j<100;j++){Taskt=Foo(100,na);while(!t.IsCompleted){na.Continue();}}Thread.Sleep(100);}for(inti=0;i<50;i++){Taskt=Foo(10_000_000,na);while(!t.IsCompleted){na.Continue();}}}staticints_value;staticasyncTaskFoo(intn,NullAwaiterna){for(inti=0;i<n;i++){s_value+=i;}Stopwatchtimer=Stopwatch.StartNew();for(inti=0;i<n;i++){awaitna;}if(n>100)Console.WriteLine("Took {0:F1} ms",timer.Elapsed.TotalMilliseconds);}privateclassNullAwaiter:ICriticalNotifyCompletion{publicActionContinue;publicNullAwaiterGetAwaiter()=>this;publicboolIsCompleted=>false;publicvoidGetResult(){}publicvoidUnsafeOnCompleted(Actioncontinuation){Continue=continuation;}publicvoidOnCompleted(Actioncontinuation){thrownewNotImplementedException();}}}

About 7-8% improvement:

-Took 268.5 ms-Took 265.9 ms-Took 267.9 ms-Took 270.0 ms-Took 269.4 ms+Took 249.4 ms+Took 248.3 ms+Took 250.3 ms+Took 249.2 ms+Took 248.9 ms
NativeAOT test sizes
BaseSizeDiffSizeDeltaPercentName
31,037,44030,944,256-93,184-0.300%System.Net.Http.Functional.Tests.exe
16,847,87216,803,328-44,544-0.264%System.Linq.AsyncEnumerable.Tests.exe
115,269,120115,089,408-179,712-0.156%System.Text.Json.SourceGeneration.Roslyn4.4.Tests.exe
20,942,33620,912,640-29,696-0.142%System.Net.Quic.Functional.Tests.exe
20,033,02420,005,376-27,648-0.138%System.Formats.Tar.Tests.exe
19,558,91219,533,824-25,088-0.128%System.IO.Compression.Tests.exe
10,055,16810,042,880-12,288-0.122%System.IO.Compression.ZipFile.Tests.exe
14,901,76014,883,840-17,920-0.120%System.Xml.Linq.Streaming.Tests.exe
16,778,75216,758,784-19,968-0.119%System.Xml.Linq.Misc.Tests.exe
28,789,76028,757,504-32,256-0.112%System.Net.Http.WinHttpHandler.Functional.Tests.exe
16,516,60816,498,176-18,432-0.112%System.Xml.Linq.Events.Tests.exe
17,065,47217,046,528-18,944-0.111%System.Xml.Linq.xNodeBuilder.Tests.exe
22,732,80022,708,224-24,576-0.108%System.Net.Sockets.Tests.exe
16,671,74416,653,824-17,920-0.107%System.Xml.Linq.Properties.Tests.exe
17,123,84017,105,920-17,920-0.105%System.Xml.Linq.TreeManipulation.Tests.exe
17,007,61616,989,696-17,920-0.105%System.Xml.Linq.xNodeReader.Tests.exe
20,003,84019,982,848-20,992-0.105%System.Net.WebSockets.Client.Tests.exe
19,053,05619,034,112-18,944-0.099%System.Net.HttpListener.Tests.exe
10,660,86410,650,624-10,240-0.096%System.IO.Pipelines.Tests.exe
20,267,00820,248,064-18,944-0.093%System.Threading.Tasks.Dataflow.Tests.exe
17,728,51217,713,664-14,848-0.084%System.Threading.Tasks.Extensions.Tests.exe
14,569,47214,557,696-11,776-0.081%System.Net.WebClient.Tests.exe
11,992,06411,982,336-9,728-0.081%System.IO.Tests.exe
21,089,79221,072,896-16,896-0.080%System.Net.Requests.Tests.exe
21,708,80021,691,392-17,408-0.080%System.IO.FileSystem.Tests.exe
10,278,91210,270,720-8,192-0.080%System.Threading.Channels.Tests.exe
27,894,27227,874,304-19,968-0.072%System.Net.Security.Tests.exe
18,447,87218,434,560-13,312-0.072%System.Threading.Tasks.Parallel.Tests.exe
13,242,36813,233,152-9,216-0.070%System.IO.Packaging.Tests.exe
9,731,0729,724,416-6,656-0.068%System.Threading.RateLimiting.Tests.exe
33,165,31233,142,784-22,528-0.068%System.Private.Xml.Tests.exe
13,869,05613,859,840-9,216-0.066%Microsoft.Extensions.Configuration.Functional.Tests.exe
19,545,60019,532,800-12,800-0.065%System.Diagnostics.Process.Tests.exe
12,849,66412,841,472-8,192-0.064%System.Xml.Schema.Extensions.Tests.exe
12,416,00012,408,320-7,680-0.062%System.Xml.Linq.SDMSample.Tests.exe
17,431,55217,420,800-10,752-0.062%System.Net.Ping.Functional.Tests.exe
20,540,41620,527,616-12,800-0.062%System.Threading.Tasks.Tests.exe
15,759,87215,750,144-9,728-0.062%System.Windows.Extensions.Tests.exe
10,056,19210,050,048-6,144-0.061%System.Net.ServerSentEvents.Tests.exe
15,102,46415,093,248-9,216-0.061%System.Drawing.Primitives.Tests.exe
17,571,84017,561,088-10,752-0.061%MetricOuterLoop1.Tests.exe
17,566,72017,555,968-10,752-0.061%MetricOuterLoop.Tests.exe
19,289,60019,277,824-11,776-0.061%System.IO.Pipes.Tests.exe
17,791,48817,780,736-10,752-0.060%System.Formats.Tar.Manual.Tests.exe
17,967,61617,956,864-10,752-0.060%System.Threading.ThreadPool.WindowsThreadPool.Tests.exe
17,329,15217,318,912-10,240-0.059%System.Threading.Timer.Tests.exe
14,130,17614,121,984-8,192-0.058%System.DirectoryServices.Protocols.Tests.exe
17,616,89617,606,656-10,240-0.058%System.Threading.Thread.Tests.exe
19,681,79219,670,528-11,264-0.057%System.Net.Http.Unit.Tests.exe
17,160,19217,150,464-9,728-0.057%System.Runtime.Serialization.Formatters.Disabled.Tests.exe
17,967,10417,956,864-10,240-0.057%System.Threading.ThreadPool.Tests.exe
19,870,72019,859,456-11,264-0.057%System.Text.Encoding.Tests.exe
18,774,01618,763,264-10,752-0.057%Microsoft.Extensions.FileProviders.Physical.Tests.exe
27,160,06427,144,704-15,360-0.057%Microsoft.Extensions.Hosting.Unit.Tests.exe
17,214,97617,205,248-9,728-0.057%System.Net.ServicePoint.Tests.exe
17,312,76817,303,040-9,728-0.056%System.Security.Principal.Windows.Tests.exe
17,230,84817,221,120-9,728-0.056%System.ComponentModel.EventBasedAsync.Tests.exe
18,128,89618,118,656-10,240-0.056%System.Diagnostics.TextWriterTraceListener.Tests.exe
17,298,94417,289,216-9,728-0.056%System.Security.Claims.Tests.exe
17,431,04017,421,312-9,728-0.056%System.Diagnostics.TraceSource.Tests.exe
17,282,04817,272,320-9,728-0.056%System.Threading.Overlapped.Tests.exe
18,177,53618,167,296-10,240-0.056%System.Text.Encoding.CodePages.Tests.exe
17,356,28817,346,560-9,728-0.056%Microsoft.Win32.SystemEvents.Tests.exe
18,586,62418,576,384-10,240-0.055%ComInterfaceGenerator.Tests.exe
17,661,44017,651,712-9,728-0.055%System.IO.FileSystem.Watcher.Tests.exe
9,251,8409,246,720-5,120-0.055%Microsoft.Bcl.AsyncInterfaces.Tests.exe
13,941,24813,933,568-7,680-0.055%Microsoft.Extensions.Configuration.Xml.Tests.exe
18,492,92818,482,688-10,240-0.055%Microsoft.Extensions.Configuration.Tests.exe
17,662,97617,653,248-9,728-0.055%System.Buffers.Tests.exe
18,489,34418,479,104-10,240-0.055%Microsoft.Extensions.Hosting.Systemd.Tests.exe
15,080,44815,072,256-8,192-0.054%System.Security.Cryptography.Cng.Tests.exe
17,154,04817,144,832-9,216-0.054%IcuAppLocal.Tests.exe
15,039,48815,031,296-8,192-0.054%System.Data.DataSetExtensions.Tests.exe
18,062,33618,052,608-9,728-0.054%System.Console.Tests.exe
17,288,19217,278,976-9,216-0.053%System.Runtime.InteropServices.RuntimeInformation.Tests.exe
17,361,40817,352,192-9,216-0.053%System.Diagnostics.StackTrace.Tests.exe
18,455,55218,445,824-9,728-0.053%Microsoft.Extensions.Configuration.FileExtensions.Tests.exe
17,235,96817,226,752-9,216-0.053%System.Runtime.InvariantTimezone.Tests.exe
18,518,01618,508,288-9,728-0.053%System.IO.MemoryMappedFiles.Tests.exe
18,693,63218,683,904-9,728-0.052%Microsoft.Extensions.Logging.Console.Tests.exe
18,032,12818,022,912-9,216-0.051%Microsoft.Extensions.Diagnostics.Tests.exe
16,107,00816,098,816-8,192-0.051%System.Data.Odbc.Tests.exe
24,284,67224,272,384-12,288-0.051%Microsoft.Extensions.Http.Tests.exe
20,532,73620,522,496-10,240-0.050%System.Runtime.Extensions.Tests.exe
18,371,58418,362,368-9,216-0.050%System.Threading.Tests.exe
18,356,73618,347,520-9,216-0.050%Microsoft.Extensions.FileProviders.Composite.Tests.exe
18,381,82418,372,608-9,216-0.050%Microsoft.Extensions.Primitives.Tests.exe
11,331,07211,325,440-5,632-0.050%System.Net.WebSockets.Tests.exe
19,295,74419,286,016-9,728-0.050%System.Net.Primitives.Functional.Tests.exe
19,972,60819,962,880-9,728-0.049%Microsoft.Extensions.Logging.Tests.exe
11,588,09611,582,464-5,632-0.049%System.Net.Http.Json.Unit.Tests.exe
19,744,76819,735,040-9,728-0.049%System.Resources.ResourceManager.Tests.exe
9,334,7849,330,176-4,608-0.049%Microsoft.Extensions.Diagnostics.Abstractions.Tests.exe
18,833,92018,824,704-9,216-0.049%System.Runtime.Caching.Tests.exe
19,080,19219,070,976-9,216-0.048%Microsoft.Extensions.Hosting.WindowsServices.Tests.exe
9,660,4169,655,808-4,608-0.048%Microsoft.Extensions.Hosting.Functional.Tests.exe
20,475,90420,466,176-9,728-0.048%System.Diagnostics.DiagnosticSource.Tests.exe
20,741,63220,731,904-9,728-0.047%System.Collections.Concurrent.Tests.exe
10,106,36810,101,760-4,608-0.046%Microsoft.Extensions.Caching.Memory.Tests.exe
20,234,75220,225,536-9,216-0.046%System.Runtime.InteropServices.Tests.exe
20,454,91220,445,696-9,216-0.045%System.Reflection.Tests.exe
19,486,20819,477,504-8,704-0.045%Microsoft.Extensions.Configuration.UserSecrets.Tests.exe
11,274,24011,269,120-5,120-0.045%System.IO.Compression.Brotli.Tests.exe
19,555,84019,547,136-8,704-0.045%Microsoft.Extensions.Configuration.Json.Tests.exe
23,405,05623,394,816-10,240-0.044%System.Memory.Tests.exe
25,891,32825,880,064-11,264-0.044%System.Text.Json.SourceGeneration.Roslyn3.11.Tests.exe
10,510,33610,505,728-4,608-0.044%Microsoft.Extensions.Options.Tests.exe
9,442,8169,438,720-4,096-0.043%Microsoft.Extensions.Logging.Testing.Tests.exe
26,440,70426,429,440-11,264-0.043%System.ComponentModel.TypeConverter.Tests.exe
21,622,78421,613,568-9,216-0.043%System.Data.OleDb.Tests.exe
26,006,52825,996,288-10,240-0.039%System.Globalization.Nls.Tests.exe
20,808,70420,801,024-7,680-0.037%System.Security.Cryptography.Csp.Tests.exe
29,403,13629,392,384-10,752-0.037%Microsoft.Extensions.DependencyModel.Tests.exe
26,095,61626,085,888-9,728-0.037%System.Globalization.Tests.exe
21,072,38421,064,704-7,680-0.036%Microsoft.Extensions.Logging.EventSource.Tests.exe
45,486,08045,470,208-15,872-0.035%System.Security.Cryptography.Tests.exe
32,739,84032,730,112-9,728-0.030%System.Linq.Expressions.Tests.exe
33,385,98433,376,256-9,728-0.029%Microsoft.Bcl.Cryptography.Tests.exe
44,704,76844,693,504-11,264-0.025%System.Runtime.Tests.exe
2,233,3442,232,832-512-0.023%clrjit.dll
10,494,46410,492,928-1,536-0.015%System.Net.Http.WinHttpHandler.Unit.Tests.exe
10,586,11210,584,576-1,536-0.015%Common.Tests.exe
9,026,0489,025,024-1,024-0.011%Microsoft.Extensions.FileSystemGlobbing.Tests.exe
9,347,5849,346,560-1,024-0.011%System.Security.Permissions.Tests.exe
9,612,8009,611,776-1,024-0.011%System.Diagnostics.EventLog.Tests.exe
12,185,08812,184,064-1,024-0.008%System.Net.NetworkInformation.Functional.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Nls.Tests.exe
15,386,11215,385,088-1,024-0.007%System.Globalization.Extensions.Tests.exe
8,743,9368,743,424-512-0.006%Invariant.Tests.exe
8,975,8728,975,360-512-0.006%System.Net.Primitives.Pal.Tests.exe
8,798,2088,797,696-512-0.006%System.Resources.Reader.Tests.exe
8,667,1368,666,624-512-0.006%System.Runtime.CompilerServices.Unsafe.Tests.exe
8,916,4808,915,968-512-0.006%System.IO.Pipes.AccessControl.Tests.exe
9,027,0729,026,560-512-0.006%System.Net.NameResolution.Pal.Tests.exe
9,191,9369,191,424-512-0.006%Microsoft.Extensions.Configuration.EnvironmentVariables.Tests.exe
8,763,9048,763,392-512-0.006%Microsoft.Bcl.TimeProvider.Tests.exe
8,609,7928,609,280-512-0.006%System.Composition.Runtime.Tests.exe
9,129,4729,128,960-512-0.006%System.Security.AccessControl.Tests.exe
8,803,3288,802,816-512-0.006%System.Web.HttpUtility.Tests.exe
9,041,9209,041,408-512-0.006%Microsoft.Extensions.Configuration.CommandLine.Tests.exe
8,638,4648,637,952-512-0.006%System.Globalization.CalendarsWithConfigSwitch.Tests.exe
8,533,5048,532,992-512-0.006%System.ComponentModel.Tests.exe
8,686,5928,686,080-512-0.006%System.Security.Cryptography.ProtectedData.Tests.exe
8,755,7128,755,200-512-0.006%System.IO.FileSystem.DriveInfo.Tests.exe
8,977,4088,976,896-512-0.006%Microsoft.Win32.Registry.Tests.exe
8,685,5688,685,056-512-0.006%System.IO.FileSystem.Manual.Tests.exe
9,095,6809,095,168-512-0.006%System.IO.FileSystem.AccessControl.Tests.exe
10,048,51210,048,000-512-0.005%System.Diagnostics.Debug.Tests.exe
11,179,52011,179,008-512-0.005%System.Text.Encodings.Web.Tests.exe
11,034,11211,033,600-512-0.005%System.Runtime.Numerics.Tests.exe
11,363,32811,362,816-512-0.005%System.Net.Security.Unit.Tests.exe
9,337,3449,336,832-512-0.005%System.IO.IsolatedStorage.Tests.exe
9,748,9929,749,504+512+0.005%System.Formats.Asn1.Tests.exe
9,473,5369,473,024-512-0.005%Microsoft.Extensions.Configuration.Ini.Tests.exe
10,936,32010,935,808-512-0.005%System.Runtime.Intrinsics.Tests.exe
9,571,3289,570,816-512-0.005%System.Memory.Data.Tests.exe
9,660,9289,660,416-512-0.005%System.IO.UnmanagedMemoryStream.Tests.exe
9,524,7369,524,224-512-0.005%System.IO.Hashing.Tests.exe
9,361,9209,361,408-512-0.005%System.Net.Mail.Unit.Tests.exe
11,590,14411,589,632-512-0.004%System.Resources.Extensions.Tests.exe
11,469,31211,468,800-512-0.004%System.IO.Ports.Tests.exe
11,779,07211,778,560-512-0.004%System.Security.Cryptography.Cose.Tests.exe
17,824,76817,824,256-512-0.003%System.Collections.Tests.exe
18,770,43218,770,944+512+0.003%System.Numerics.Vectors.Tests.exe
22,320,64022,320,128-512-0.002%System.Security.Cryptography.Pkcs.Tests.exe
8,988,6728,988,67200.000%System.Runtime.Serialization.Primitives.Tests.exe
8,690,1768,690,17600.000%System.Security.SecureString.Tests.exe
9,201,6649,201,66400.000%System.ServiceProcess.ServiceController.Tests.exe
7,318,0167,318,01600.000%XUnitLogChecker.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
84,48084,48000.000%System.Globalization.Native.dll
108,032108,03200.000%CMakeCXXCompilerId.exe
108,032108,03200.000%CMakeCCompilerId.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
8,673,2808,673,28000.000%System.Runtime.InteropServices.ComDisabled.Tests.exe
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,608,7688,608,76800.000%System.Xml.Linq.Axes.Tests.exe
9,069,0569,069,05600.000%System.ValueTuple.Tests.exe
8,945,1528,945,15200.000%System.Threading.AccessControl.Tests.exe
9,690,1129,690,11200.000%System.Text.RegularExpressions.Unit.Tests.exe
8,543,2328,543,23200.000%System.Text.Encoding.Extensions.Tests.exe
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
536,096536,09600.000%msquic.dll
8,529,4088,529,40800.000%System.IO.FileSystem.Primitives.Tests.exe
8,532,4808,532,48000.000%System.Runtime.CompilerServices.VisualC.Tests.exe
536,096536,09600.000%msquic.dll
1,308,6721,308,67200.000%mscordbi.dll
1,501,6961,501,69600.000%mscordaccore.dll
1,501,6961,501,69600.000%mscordaccore_amd64_amd64_42.42.42.42424.dll
361,984361,98400.000%hostpolicy.dll
350,208350,20800.000%hostfxr.dll
62,46462,46400.000%createdump.exe
210,944210,94400.000%corerun.exe
4,955,6484,955,64800.000%coreclr.dll
722,944722,94400.000%clrgcexp.dll
678,400678,40000.000%clrgc.dll
307,200307,20000.000%clretwrc.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
84,48084,48000.000%System.Globalization.Native.dll
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
696,320696,32000.000%FileCheck.exe
9,956,3529,956,35200.000%llvm-mca.exe
13,419,52013,419,52000.000%crossgen2.exe
7,703,0407,703,04000.000%ilasm.exe
1,377,2801,377,28000.000%System.IO.Compression.Native.dll
15,940,09615,940,09600.000%ilc.exe
8,938,4968,938,49600.000%Microsoft.Bcl.Memory.Tests.exe
8,578,0488,578,04800.000%Microsoft.Bcl.Numerics.Tests.exe
8,587,2648,587,26400.000%Microsoft.Extensions.Hosting.Abstractions.Tests.exe
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
9,947,6489,947,64800.000%LibraryImportGenerator.Tests.exe
8,655,8728,655,87200.000%System.Runtime.Handles.Tests.exe
16,973,82416,973,82400.000%System.Private.CoreLib.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
8,591,3608,591,36000.000%System.Resources.Writer.Tests.exe
9,011,2009,011,20000.000%System.Reflection.TypeExtensions.Tests.exe
12,271,10412,271,10400.000%System.Reflection.Metadata.Tests.exe
8,849,9208,849,92000.000%System.Reflection.Extensions.Tests.exe
9,350,6569,350,65600.000%System.Reflection.Context.Tests.exe
8,704,5128,704,51200.000%System.Private.Uri.Unit.Tests.exe
9,631,7449,631,74400.000%System.Private.Uri.Functional.Tests.exe
9,785,8569,785,85600.000%System.Net.WebProxy.Tests.exe
8,627,2008,627,20000.000%System.Net.WebHeaderCollection.Tests.exe
9,300,9929,300,99200.000%System.Net.Primitives.UnitTests.Tests.exe
15,486,97615,486,97600.000%System.Linq.Tests.exe
696,320696,32000.000%FileCheck.exe
9,150,9769,150,97600.000%System.Globalization.Calendars.Tests.exe
9,837,5689,837,56800.000%System.Formats.Nrbf.Tests.exe
8,534,5288,534,52800.000%System.Diagnostics.Tools.Tests.exe
8,702,4648,702,46400.000%System.Diagnostics.FileVersionInfo.Tests.exe
8,547,8408,547,84000.000%System.Diagnostics.Contracts.Tests.exe
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
1,754,5121,754,51200.000%Microsoft.DiaSymReader.Native.arm.dll
2,247,7842,247,78400.000%Microsoft.DiaSymReader.Native.arm64.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
1,935,2961,935,29600.000%Microsoft.DiaSymReader.Native.x86.dll
2,309,1522,309,15200.000%Microsoft.DiaSymReader.Native.amd64.dll
8,649,2168,649,21600.000%Microsoft.Win32.Primitives.Tests.exe
9,934,3369,934,33600.000%System.Collections.NonGeneric.Tests.exe
9,734,6569,734,65600.000%System.Collections.Specialized.Tests.exe
9,147,3929,147,39200.000%System.ComponentModel.Primitives.Tests.exe
8,544,7688,544,76800.000%System.Composition.AttributeModel.Tests.exe
9,615,8729,615,87200.000%System.Composition.Convention.Tests.exe
8,821,7608,821,76000.000%System.Console.Manual.Tests.exe
8,632,8328,632,83200.000%Microsoft.Win32.Registry.AccessControl.Tests.exe
9,956,3529,956,35200.000%llvm-mca.exe

Remove `RestoreExecutionContext` call from JIT resumption code and from
the interpreter. Instead encode the `ExecutionContext`'s location in the
continuation and let the dispatcher restore it. This removes a TLS
access + helper call from the resumption path (avoiding the TLS and
inlining the helper call in the dispatcher).
Improves suspension/resumption performance by about 5-6% and should also
be a small size improvement.
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes CoreCLR runtime-async suspension/resumption so the dispatcher (managed AsyncHelpers) restores ExecutionContext, instead of having interpreter/JIT resumption stubs call a restore helper. The continuation’s flags now encode the ExecutionContext storage slot, enabling the dispatcher to restore without an extra TLS lookup + helper call on the hot resumption path.

Changes:

  • Add continuation support for locating/storing the ExecutionContext via encoded indices in continuation flags (VM + managed + JIT + interpreter).
  • Remove RestoreExecutionContext calls from interpreter and JIT resumption code; add restoration to the dispatcher loop.
  • Preserve BBF_ASYNC_RESUMPTION across certain flow optimizations that may bypass resumption stubs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/vm/object.hAdds VM helper to locate ExecutionContext storage in a continuation via encoded flag bits.
src/coreclr/vm/interpexec.cppWrites captured ExecutionContext via the encoded slot; removes interpreter-side restore on resume.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.csMoves ExecutionContext restore into dispatcher; adjusts flag layout and RestoreExecutionContext signature to avoid TLS lookup.
src/coreclr/jit/fgopt.cppCopies BBF_ASYNC_RESUMPTION during certain jump/switch/flow optimizations to preserve async side-entry affordances.
src/coreclr/jit/async.cppUpdates continuation layout/flag encoding for ExecutionContext; removes JIT-side restore on resumption.
src/coreclr/interpreter/inc/interpretershared.hRemoves interpreter suspend-data field that stored a raw execution-context offset.
src/coreclr/interpreter/compiler.cppEncodes ExecutionContext slot in flags and updates interpreter continuation layout accordingly.
src/coreclr/inc/corinfo.hUpdates CorInfoContinuationFlags bit assignments to include ExecutionContext index encoding.
Comments suppressed due to low confidence (2)

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:554

  • RuntimeAsyncStackState contains managed reference fields, but this local is left uninitialized before its address is stored in TLS (awaitState.Push(&stackState)). This can expose garbage references to the GC (and Push only initializes a subset of fields), risking GC crashes/corruption. Initialize stackState to default (or otherwise fully clear all reference fields before any GC safepoint) before calling Push.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs:655

  • Same issue as in DispatchContinuations: RuntimeAsyncStackState stackState; is uninitialized even though the struct contains managed references and its address is pushed into TLS via awaitState.Push(&stackState). This can leave garbage object references visible to the GC until fields are explicitly set. Ensure stackState is zero-initialized (e.g., = default) or otherwise cleared before pushing.
 RuntimeAsyncStackState stackState;
ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
awaitState.Push(&stackState);

CopilotAI review requested due to automatic review settings April 29, 2026 09:11

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • InterpAsyncSuspendData.restoreExecutionContextMethod is still populated, but after removing the interpreter-side RestoreExecutionContext call there don’t appear to be any remaining reads of this field. Consider removing the field from InterpAsyncSuspendData (and this assignment) to reduce per-suspension metadata size and avoid dead state.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

CopilotAI review requested due to automatic review settings April 30, 2026 11:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/coreclr/interpreter/compiler.cpp:6007

  • CORINFO_ASYNC_INFO no longer exposes restoreExecutionContextMethHnd, but the interpreter still stores asyncInfo.restoreExecutionContextMethHnd into InterpAsyncSuspendData. This will fail to compile and should be removed/rewired now that execution context restoration is done by the dispatcher.
 suspendData->keepAliveOffset = keepAliveOffset + OFFSETOF__CORINFO_Continuation__data;
suspendData->captureSyncContextMethod = asyncInfo.captureContinuationContextMethHnd;
suspendData->restoreExecutionContextMethod = asyncInfo.restoreExecutionContextMethHnd;
suspendData->restoreContextsOnSuspensionMethod = asyncInfo.restoreContextsOnSuspensionMethHnd;

Comment threadsrc/coreclr/inc/corinfo.h
Comment threadsrc/coreclr/vm/corelib.h
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Comment threadsrc/coreclr/interpreter/inc/interpretershared.h
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Comment threadsrc/coreclr/jit/async.cpp
Comment threadsrc/coreclr/jit/fgbasic.cpp
CopilotAI review requested due to automatic review settings April 30, 2026 12:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/interpexec.cpp
Comment threaddocs/design/coreclr/botr/runtime-async-codegen.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings April 30, 2026 12:38

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/interpexec.cpp

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @VSadov (async) @AndyAyersMS (JIT) @davidwrighton /@janvorli (interpreter)

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIT changes look good.

Comment threadsrc/coreclr/jit/fgbasic.cpp

@VSadovVSadov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Will merge this, @janvorli@davidwrighton let me know if you have any comments on the interpreter change and I can address it in a follow-up.

@jakobbotsch
jakobbotsch merged commit 83ebc00 into dotnet:mainMay 4, 2026
124 checks passed
@jakobbotsch
jakobbotsch deleted the restore-execution-context-in-dispatcher branch May 4, 2026 11:06
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@VSadov@AndyAyersMS