From 6547e8cdda23530d057dc3664923392f0e7f3c90 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 4 Aug 2025 22:49:23 -0400 Subject: [PATCH] Fix perf bug in RegexCompiler when handling .*? We have a special-code path that exists to optimize a singleline `.*?`, in which case we can just search for what comes after the loop in the pattern because the loop itself will lazily match everything. Unfortunately, we're passing the wrong node to the EmitIndexOf helper that emits that search. We should be passing the node which represents the subsequent literal, but we're accidentally passing the set loop itself. We're only here if that set loop matches everything, so we're emitting an IndexOfAnyInRange(0, \uFFFF) call. This is functionally ok, but perf tanks because we end up needing to do non-trivial work for every character that matches the loop. --- .../src/System/Text/RegularExpressions/RegexCompiler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs index 43e9dd324eb162..f4b6c25f227b90 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs @@ -3753,7 +3753,7 @@ node.Kind is RegexNodeKind.Setlazy && // startingPos = slice.IndexOf(literal); Ldloc(slice); - EmitIndexOf(node, useLast: false, negate: false); + EmitIndexOf(literal2, useLast: false, negate: false); Stloc(startingPos); // if (startingPos < 0) goto doneLabel;