@@ -64,6 +64,7 @@ internal abstract class RegexCompiler
64
64
private static readonly MethodInfo s_spanSliceIntIntMethod = typeof ( ReadOnlySpan < char > ) . GetMethod ( "Slice" , new Type [ ] { typeof ( int ) , typeof ( int ) } ) ! ;
65
65
private static readonly MethodInfo s_spanStartsWith = typeof ( MemoryExtensions ) . GetMethod ( "StartsWith" , new Type [ ] { typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) , typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) } ) ! . MakeGenericMethod ( typeof ( char ) ) ;
66
66
private static readonly MethodInfo s_stringAsSpanMethod = typeof ( MemoryExtensions ) . GetMethod ( "AsSpan" , new Type [ ] { typeof ( string ) } ) ! ;
67
+ private static readonly MethodInfo s_spanLastIndexOfMethod = typeof ( MemoryExtensions ) . GetMethod ( "LastIndexOf" , new Type [ ] { typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) , typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) } ) ! . MakeGenericMethod ( typeof ( char ) ) ;
67
68
private static readonly MethodInfo s_stringAsSpanIntIntMethod = typeof ( MemoryExtensions ) . GetMethod ( "AsSpan" , new Type [ ] { typeof ( string ) , typeof ( int ) , typeof ( int ) } ) ! ;
68
69
private static readonly MethodInfo s_stringGetCharsMethod = typeof ( string ) . GetMethod ( "get_Chars" , new Type [ ] { typeof ( int ) } ) ! ;
69
70
private static readonly MethodInfo s_stringIndexOfCharInt = typeof ( string ) . GetMethod ( "IndexOf" , new Type [ ] { typeof ( char ) , typeof ( int ) } ) ! ;
@@ -90,6 +91,7 @@ internal abstract class RegexCompiler
90
91
private LocalBuilder ? _runstackLocal ;
91
92
private LocalBuilder ? _textInfoLocal ; // cached to avoid extraneous TLS hits from CurrentCulture and virtual calls to TextInfo
92
93
private LocalBuilder ? _loopTimeoutCounterLocal ; // timeout counter for setrep and setloop
94
+ private LocalBuilder ? _maxBacktrackPositionLocal ;
93
95
94
96
protected RegexOptions _options ; // options
95
97
protected RegexCode ? _code ; // the RegexCode object
@@ -891,6 +893,8 @@ private void GenerateForwardSection()
891
893
Mvfldloc ( s_runtrackposField , _runtrackposLocal ! ) ;
892
894
Mvfldloc ( s_runstackField , _runstackLocal ! ) ;
893
895
Mvfldloc ( s_runstackposField , _runstackposLocal ! ) ;
896
+ Ldc ( - 1 ) ;
897
+ Stloc ( _maxBacktrackPositionLocal ! ) ;
894
898
895
899
_backpos = - 1 ;
896
900
@@ -1705,7 +1709,7 @@ protected void GenerateFindFirstChar()
1705
1709
// if (!CharInClass(textSpan[i + 2], prefix[2], "...")) goto returnFalse;
1706
1710
// ...
1707
1711
Debug . Assert ( charClassIndex == 0 || charClassIndex == 1 ) ;
1708
- for ( ; charClassIndex < _leadingCharClasses . Length ; charClassIndex ++ )
1712
+ for ( ; charClassIndex < _leadingCharClasses . Length ; charClassIndex ++ )
1709
1713
{
1710
1714
Debug . Assert ( needLoop ) ;
1711
1715
Ldloca ( textSpanLocal ) ;
@@ -3310,6 +3314,7 @@ protected void GenerateGo()
3310
3314
}
3311
3315
_runtextbegLocal = DeclareInt32 ( ) ;
3312
3316
_runtextendLocal = DeclareInt32 ( ) ;
3317
+ _maxBacktrackPositionLocal = DeclareInt32 ( ) ;
3313
3318
3314
3319
InitializeCultureForGoIfNecessary ( ) ;
3315
3320
@@ -4258,7 +4263,61 @@ private void GenerateOneCode()
4258
4263
//: break Backward;
4259
4264
{
4260
4265
string str = _strings ! [ Operand ( 0 ) ] ;
4266
+ Label multiCode = DefineLabel ( ) ;
4267
+ if ( ! IsRightToLeft ( ) )
4268
+ {
4269
+ // if (runtextend - runtextpos < c)
4270
+ Ldloc ( _runtextendLocal ! ) ;
4271
+ Ldloc ( _runtextposLocal ! ) ;
4272
+ Sub ( ) ;
4273
+ Ldc ( str . Length ) ;
4274
+ BgeFar ( multiCode ) ;
4275
+ // if (!caseInsensitive && _maxBacktrackPosition != -1 && runtextpos > _maxBacktrackPosition)
4276
+ if ( ! IsCaseInsensitive ( ) )
4277
+ {
4278
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4279
+ Ldc ( - 1 ) ;
4280
+ BeqFar ( _backtrack ) ;
4281
+ Ldloc ( _runtextposLocal ! ) ;
4282
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4283
+ BleFar ( _backtrack ) ;
4284
+ // runtextpos = _maxBacktrackPosition;
4285
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4286
+ Stloc ( _runtextposLocal ! ) ;
4287
+ // ReadOnlySpan<char> runtextSpan = runtext.AsSpan(_maxBacktrackPosition, runtextend - _maxBacktractPosition);
4288
+ Ldloc ( _runtextLocal ! ) ;
4289
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4290
+ Ldloc ( _runtextendLocal ! ) ;
4291
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4292
+ Sub ( ) ;
4293
+ using ( RentedLocalBuilder runtextSpanLocal = RentReadOnlySpanCharLocal ( ) )
4294
+ {
4295
+ Call ( s_stringAsSpanIntIntMethod ) ;
4296
+ Stloc ( runtextSpanLocal ) ;
4297
+ using ( RentedLocalBuilder lastIndexOfLocal = RentInt32Local ( ) )
4298
+ {
4299
+ // int lastIndexOf = runtextSpan.LastIndexOf(str.AsSpan());
4300
+ Ldloc ( runtextSpanLocal ) ;
4301
+ Ldstr ( str ) ;
4302
+ Call ( s_stringAsSpanMethod ) ;
4303
+ Call ( s_spanLastIndexOfMethod ) ;
4304
+ Stloc ( lastIndexOfLocal ) ;
4305
+ // if (lastIndexOf > -1)
4306
+ Ldloc ( lastIndexOfLocal ) ;
4307
+ Ldc ( - 1 ) ;
4308
+ BleFar ( _backtrack ) ;
4309
+ // runtextpos = lastIndexOf + _maxBacktrackPosition;
4310
+ Ldloc ( lastIndexOfLocal ) ;
4311
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4312
+ Add ( ) ;
4313
+ Stloc ( _runtextposLocal ! ) ;
4314
+ BrFar ( _backtrack ) ;
4315
+ }
4316
+ }
4317
+ }
4318
+ }
4261
4319
4320
+ MarkLabel ( multiCode ) ;
4262
4321
Ldc ( str . Length ) ;
4263
4322
Ldloc ( _runtextendLocal ! ) ;
4264
4323
Ldloc ( _runtextposLocal ! ) ;
@@ -4598,6 +4657,9 @@ private void GenerateOneCode()
4598
4657
4599
4658
using RentedLocalBuilder lenLocal = RentInt32Local ( ) ;
4600
4659
using RentedLocalBuilder iLocal = RentInt32Local ( ) ;
4660
+ using RentedLocalBuilder tempMaxBacktrackPositionLocal = RentInt32Local ( ) ;
4661
+ Ldloc ( _runtextposLocal ! ) ;
4662
+ Stloc ( tempMaxBacktrackPositionLocal ) ;
4601
4663
4602
4664
if ( ! IsRightToLeft ( ) )
4603
4665
{
@@ -4847,6 +4909,12 @@ private void GenerateOneCode()
4847
4909
DoPush ( ) ;
4848
4910
4849
4911
Track ( ) ;
4912
+ // if (_operator == RegexCode.Notoneloop) maxBacktrackPosition = tempMaxBacktrackPosition
4913
+ if ( _regexopcode == RegexCode . Notoneloop )
4914
+ {
4915
+ Ldloc ( tempMaxBacktrackPositionLocal ) ;
4916
+ Stloc ( _maxBacktrackPositionLocal ! ) ;
4917
+ }
4850
4918
}
4851
4919
break ;
4852
4920
}
@@ -4870,28 +4938,66 @@ private void GenerateOneCode()
4870
4938
//: if (i > 0)
4871
4939
//: Track(i - 1, pos - 1);
4872
4940
//: Advance(2);
4873
- PopTrack ( ) ;
4874
- Stloc ( _runtextposLocal ! ) ;
4941
+ Label noBacktrackPositionBranch = DefineLabel ( ) ;
4875
4942
PopTrack ( ) ;
4876
4943
using ( RentedLocalBuilder posLocal = RentInt32Local ( ) )
4877
4944
{
4878
4945
Stloc ( posLocal ) ;
4879
- Ldloc ( posLocal ) ;
4880
- Ldc ( 0 ) ;
4881
- BleFar ( AdvanceLabel ( ) ) ;
4946
+ PopTrack ( ) ;
4947
+ using ( RentedLocalBuilder iBacktrackLocal = RentInt32Local ( ) )
4948
+ {
4949
+ Stloc ( iBacktrackLocal ) ;
4950
+ // if (!caseInsensitive && maxBacktrackPosition != -1 && pos > maxBacktrackPosition && runtextpos < pos && _operator == (RegexCode.Notoneloop | RegexCode.Back) && !_rightToLeft)
4951
+ if ( ! IsCaseInsensitive ( ) && _regexopcode == ( RegexCode . Notoneloop | RegexCode . Back ) && ! IsRightToLeft ( ) )
4952
+ {
4953
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4954
+ Ldc ( - 1 ) ;
4955
+ Beq ( noBacktrackPositionBranch ) ;
4956
+ Ldloc ( posLocal ) ;
4957
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4958
+ Ble ( noBacktrackPositionBranch ) ;
4959
+ Ldloc ( _runtextposLocal ! ) ;
4960
+ Ldloc ( posLocal ) ;
4961
+ Bge ( noBacktrackPositionBranch ) ;
4962
+ /*
4963
+ int difference = pos - maxBacktrackPosition;
4964
+ pos = runtextpos;
4965
+ i -= difference;
4966
+ maxBacktrackPosition = -1;
4967
+ */
4968
+ // int difference = pos - maxBacktrackPosition;
4969
+ Ldloc ( iBacktrackLocal ) ;
4970
+ Ldloc ( posLocal ) ;
4971
+ Ldloc ( _maxBacktrackPositionLocal ! ) ;
4972
+ Sub ( ) ;
4973
+ Sub ( ) ;
4974
+ Stloc ( iBacktrackLocal ) ;
4975
+ Ldloc ( _runtextposLocal ! ) ;
4976
+ Stloc ( posLocal ) ;
4977
+ Ldc ( - 1 ) ;
4978
+ Stloc ( _maxBacktrackPositionLocal ! ) ;
4979
+ }
4980
+
4981
+ MarkLabel ( noBacktrackPositionBranch ) ;
4982
+ Ldloc ( posLocal ) ;
4983
+ Stloc ( _runtextposLocal ! ) ;
4984
+ Ldloc ( iBacktrackLocal ) ;
4985
+ Ldc ( 0 ) ;
4986
+ BleFar ( AdvanceLabel ( ) ) ;
4987
+ ReadyPushTrack ( ) ;
4988
+ Ldloc ( iBacktrackLocal ) ;
4989
+ }
4990
+ Ldc ( 1 ) ;
4991
+ Sub ( ) ;
4992
+ DoPush ( ) ;
4882
4993
ReadyPushTrack ( ) ;
4883
- Ldloc ( posLocal ) ;
4994
+ Ldloc ( _runtextposLocal ! ) ;
4995
+ Ldc ( 1 ) ;
4996
+ Sub ( IsRightToLeft ( ) ) ;
4997
+ DoPush ( ) ;
4998
+ Trackagain ( ) ;
4999
+ Advance ( ) ;
4884
5000
}
4885
- Ldc ( 1 ) ;
4886
- Sub ( ) ;
4887
- DoPush ( ) ;
4888
- ReadyPushTrack ( ) ;
4889
- Ldloc ( _runtextposLocal ! ) ;
4890
- Ldc ( 1 ) ;
4891
- Sub ( IsRightToLeft ( ) ) ;
4892
- DoPush ( ) ;
4893
- Trackagain ( ) ;
4894
- Advance ( ) ;
4895
5001
break ;
4896
5002
4897
5003
case RegexCode . Onelazy :
0 commit comments