Skip to content

Commit 5ad6dc0

Browse files
committed
small changes
1 parent 2b9e7b2 commit 5ad6dc0

File tree

2 files changed

+12
-11
lines changed

2 files changed

+12
-11
lines changed

src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/MatchingState.cs

+1-6
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,7 @@ internal MatchingState(SymbolicRegexNode<TSet> node, uint prevCharKind)
1818
}
1919

2020
/// <summary>
21-
/// TODO: The CLR assigns an entire field for this byte which is a waste,
22-
/// and the much more preferred way to use this is in _nullabilityArray in the matcher
23-
/// but the current design relies on interfaces/flags and
24-
/// using the MatchingState directly so this byte is a quick solution to cheapen
25-
/// it there by ~30% as well without having to breaking it all to pieces.
26-
/// removing IsNullableFor in other places requires major redesign
21+
/// TODO: This is only used to speed up the existing architecture, ideally should be removed along with IsNullableFor
2722
/// </summary>
2823
internal readonly int NullabilityInfo;
2924

src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexMatcher.cs

+11-5
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ internal sealed partial class SymbolicRegexMatcher<TSet> : SymbolicRegexMatcher
8181
/// <summary>Data and routines for skipping ahead to the next place a match could potentially start.</summary>
8282
private readonly RegexFindOptimizations? _findOpts;
8383

84-
/// <summary>Dead end state to quickly return NoMatch</summary>
84+
/// <summary>Dead end state to quickly return NoMatch, this could potentially be a constant</summary>
8585
private readonly int _deadStateId;
8686

8787
/// <summary>Whether the pattern contains any anchor</summary>
@@ -663,6 +663,7 @@ private bool FindEndPositionDeltasDFANoSkipAscii(ReadOnlySpan<char> input, int l
663663
/// TODO: this is essentially a stripped down version when there's no good prefix optimizations
664664
/// i don't trust the compiler to optimize this and it makes a
665665
/// ~50% difference in performance with removing unnecessary checks alone
666+
///
666667
/// </summary>
667668
private bool FindEndPositionDeltasDFANoSkip(ReadOnlySpan<char> input, int lengthMinus1, RegexRunnerMode mode,
668669
ref int posRef, int startStateId, ref int endPosRef, ref int endStateIdRef, ref int initialStatePosRef, ref int initialStatePosCandidateRef)
@@ -674,12 +675,19 @@ private bool FindEndPositionDeltasDFANoSkip(ReadOnlySpan<char> input, int length
674675
byte[] mtlookup = _mintermClassifier.ByteLookup()!;
675676
int endStateId = endStateIdRef;
676677
int currStateId = startStateId;
678+
// ldfld only once
679+
int deadStateId = _deadStateId;
677680
try
678681
{
679682
// Loop through each character in the input, transitioning from state to state for each.
683+
// The goal is to make this loop as fast as it can possible be,
684+
// every single piece of overhead should be removed here
685+
// there should be not a single callvirt instruction in the loop
686+
// ldfld only if necessary (e.g. a reference changes)
687+
// no memory writes unless necessary
680688
while (true)
681689
{
682-
if (currStateId == _deadStateId)
690+
if (currStateId == deadStateId)
683691
{
684692
return true;
685693
}
@@ -709,9 +717,7 @@ private bool FindEndPositionDeltasDFANoSkip(ReadOnlySpan<char> input, int length
709717
}
710718
// one off check for the final position
711719
// this is just to move it out of the hot loop
712-
if ((!_stateFlagsArray[currStateId].IsNullable() &&
713-
!_stateArray[currStateId]!.IsNullableFor(
714-
GetPositionKind(-1))))
720+
if ((!_stateFlagsArray[currStateId].IsNullable() && IsNullableWithContext(currStateId, 0)))
715721
{
716722
return false;
717723
}

0 commit comments

Comments
 (0)