diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index cd5eb03827ffbd..dc92e4bd893f62 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -2713,7 +2713,7 @@ public async Task StressTestDeepNestingOfLoops(RegexEngine engine, string begin, } } - [ConditionalTheory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))] // deep nesting exhausts address space on 32-bit [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Fix is not available on .NET Framework")] [MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))] public async Task CharClassSubtraction_DeepNesting_DoesNotStackOverflow(RegexEngine engine) diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs index 946b1d2f1be6e9..6644119e4016d8 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs @@ -146,7 +146,7 @@ internal static async Task SourceGenRegexAsync( (string pattern, CultureInfo? culture, RegexOptions? options, TimeSpan? matchTimeout)[] regexes, CancellationToken cancellationToken = default) { // Un-ifdef to compile each regex individually, which can be useful if one regex among thousands is causing a failure. - // We compile them all en mass for test efficiency, but it can make it harder to debug a compilation failure in one of them. + // We compile them all en masse for test efficiency, but it can make it harder to debug a compilation failure in one of them. #if false if (regexes.Length > 1) { @@ -159,6 +159,20 @@ internal static async Task SourceGenRegexAsync( } #endif + // On 32-bit processes the ~2GB address space limit can cause OutOfMemoryException + // when Roslyn compiles thousands of patterns at once. Chunk into smaller batches + // on 32-bit to avoid OOM while keeping full batching on 64-bit. + const int MaxBatchSize = 200; + if (!Environment.Is64BitProcess && regexes.Length > MaxBatchSize) + { + var batchResults = new List(regexes.Length); + foreach (var chunk in regexes.Chunk(MaxBatchSize)) + { + batchResults.AddRange(await SourceGenRegexAsync(chunk, cancellationToken)); + } + return batchResults.ToArray(); + } + Debug.Assert(regexes.Length > 0); var code = new StringBuilder();