@@ -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