@@ -49,13 +49,12 @@ internal abstract class RegexCompiler
49
49
private static readonly MethodInfo s_spanIndexOfAnyCharChar = typeof ( MemoryExtensions ) . GetMethod ( "IndexOfAny" , new Type [ ] { typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) , Type . MakeGenericMethodParameter ( 0 ) , Type . MakeGenericMethodParameter ( 0 ) } ) ! . MakeGenericMethod ( typeof ( char ) ) ;
50
50
private static readonly MethodInfo s_spanIndexOfAnyCharCharChar = typeof ( MemoryExtensions ) . GetMethod ( "IndexOfAny" , new Type [ ] { typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) , Type . MakeGenericMethodParameter ( 0 ) , Type . MakeGenericMethodParameter ( 0 ) , Type . MakeGenericMethodParameter ( 0 ) } ) ! . MakeGenericMethod ( typeof ( char ) ) ;
51
51
private static readonly MethodInfo s_spanIndexOfAnySpan = typeof ( MemoryExtensions ) . GetMethod ( "IndexOfAny" , new Type [ ] { typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) , typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) } ) ! . MakeGenericMethod ( typeof ( char ) ) ;
52
+ private static readonly MethodInfo s_spanLastIndexOfChar = typeof ( MemoryExtensions ) . GetMethod ( "LastIndexOf" , new Type [ ] { typeof ( ReadOnlySpan < > ) . MakeGenericType ( Type . MakeGenericMethodParameter ( 0 ) ) , Type . MakeGenericMethodParameter ( 0 ) } ) ! . MakeGenericMethod ( typeof ( char ) ) ;
52
53
private static readonly MethodInfo s_spanSliceIntMethod = typeof ( ReadOnlySpan < char > ) . GetMethod ( "Slice" , new Type [ ] { typeof ( int ) } ) ! ;
53
54
private static readonly MethodInfo s_spanSliceIntIntMethod = typeof ( ReadOnlySpan < char > ) . GetMethod ( "Slice" , new Type [ ] { typeof ( int ) , typeof ( int ) } ) ! ;
54
55
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 ) ) ;
55
56
private static readonly MethodInfo s_stringAsSpanMethod = typeof ( MemoryExtensions ) . GetMethod ( "AsSpan" , new Type [ ] { typeof ( string ) } ) ! ;
56
- private static readonly MethodInfo s_stringAsSpanIntIntMethod = typeof ( MemoryExtensions ) . GetMethod ( "AsSpan" , new Type [ ] { typeof ( string ) , typeof ( int ) , typeof ( int ) } ) ! ;
57
57
private static readonly MethodInfo s_stringGetCharsMethod = typeof ( string ) . GetMethod ( "get_Chars" , new Type [ ] { typeof ( int ) } ) ! ;
58
- private static readonly MethodInfo s_stringLastIndexOfCharIntInt = typeof ( string ) . GetMethod ( "LastIndexOf" , new Type [ ] { typeof ( char ) , typeof ( int ) , typeof ( int ) } ) ! ;
59
58
private static readonly MethodInfo s_textInfoToLowerMethod = typeof ( TextInfo ) . GetMethod ( "ToLower" , new Type [ ] { typeof ( char ) } ) ! ;
60
59
private static readonly MethodInfo s_arrayResize = typeof ( Array ) . GetMethod ( "Resize" ) ! . MakeGenericMethod ( typeof ( int ) ) ;
61
60
@@ -889,7 +888,7 @@ protected void EmitGo()
889
888
}
890
889
891
890
// Initialize the main locals used throughout the implementation.
892
- LocalBuilder runtextLocal = DeclareString ( ) ;
891
+ LocalBuilder runtextSpanLocal = DeclareReadOnlySpanChar ( ) ;
893
892
LocalBuilder originalruntextposLocal = DeclareInt32 ( ) ;
894
893
LocalBuilder runtextposLocal = DeclareInt32 ( ) ;
895
894
LocalBuilder textSpanLocal = DeclareReadOnlySpanChar ( ) ;
@@ -905,9 +904,11 @@ protected void EmitGo()
905
904
// CultureInfo culture = CultureInfo.CurrentCulture; // only if the whole expression or any subportion is ignoring case, and we're not using invariant
906
905
InitializeCultureForGoIfNecessary ( ) ;
907
906
908
- // string runtext = this.runtext;
907
+ // ReadOnlySpan<char> runtextSpan = this.runtext.AsSpan() ;
909
908
// int runtextend = this.runtextend;
910
- Mvfldloc ( s_runtextField , runtextLocal ) ;
909
+ Ldthisfld ( s_runtextField ) ;
910
+ Call ( s_stringAsSpanMethod ) ;
911
+ Stloc ( runtextSpanLocal ) ;
911
912
Mvfldloc ( s_runtextendField , runtextendLocal ) ;
912
913
913
914
// int runtextpos = this.runtextpos;
@@ -996,13 +997,13 @@ protected void EmitGo()
996
997
// Creates a span for runtext starting at runtextpos until this.runtextend.
997
998
void LoadTextSpanLocal ( )
998
999
{
999
- // textSpan = runtext.AsSpan (runtextpos, this.runtextend - runtextpos);
1000
- Ldloc ( runtextLocal ) ;
1000
+ // textSpan = runtextSpan.Slice (runtextpos, this.runtextend - runtextpos);
1001
+ Ldloca ( runtextSpanLocal ) ;
1001
1002
Ldloc ( runtextposLocal ) ;
1002
1003
Ldloc ( runtextendLocal ) ;
1003
1004
Ldloc ( runtextposLocal ) ;
1004
1005
Sub ( ) ;
1005
- Call ( s_stringAsSpanIntIntMethod ) ;
1006
+ Call ( s_spanSliceIntIntMethod ) ;
1006
1007
Stloc ( textSpanLocal ) ;
1007
1008
}
1008
1009
@@ -1292,12 +1293,13 @@ void EmitBackreference(RegexNode node)
1292
1293
1293
1294
MarkLabel ( body ) ;
1294
1295
1295
- // if (runtext [matchIndex + i] != textSpan[i]) goto doneLabel;
1296
- Ldloc ( runtextLocal ) ;
1296
+ // if (runtextSpan [matchIndex + i] != textSpan[i]) goto doneLabel;
1297
+ Ldloca ( runtextSpanLocal ) ;
1297
1298
Ldloc ( matchIndex ) ;
1298
1299
Ldloc ( i ) ;
1299
1300
Add ( ) ;
1300
- Call ( s_stringGetCharsMethod ) ;
1301
+ Call ( s_spanGetItemMethod ) ;
1302
+ LdindU2 ( ) ;
1301
1303
if ( IsCaseInsensitive ( node ) )
1302
1304
{
1303
1305
CallToLower ( ) ;
@@ -2092,11 +2094,12 @@ void EmitAnchors(RegexNode node)
2092
2094
Ldloc ( runtextposLocal ) ;
2093
2095
Ldthisfld ( s_runtextbegField ) ;
2094
2096
Ble ( success ) ;
2095
- Ldthisfld ( s_runtextField ) ;
2097
+ Ldloca ( runtextSpanLocal ) ;
2096
2098
Ldloc ( runtextposLocal ) ;
2097
2099
Ldc ( 1 ) ;
2098
2100
Sub ( ) ;
2099
- Call ( s_stringGetCharsMethod ) ;
2101
+ Call ( s_spanGetItemMethod ) ;
2102
+ LdindU2 ( ) ;
2100
2103
Ldc ( '\n ' ) ;
2101
2104
BneFar ( doneLabel ) ;
2102
2105
MarkLabel ( success ) ;
@@ -2328,24 +2331,29 @@ void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitL
2328
2331
2329
2332
if ( subsequent ? . FindStartingCharacter ( ) is char subsequentCharacter )
2330
2333
{
2331
- // endingPos = runtext.LastIndexOf(subsequentCharacter , endingPos - 1, endingPos - startingPos);
2334
+ // endingPos = runtextSpan.Slice(startingPos , endingPos - startingPos).LastIndexOf(subsequentCharacter );
2332
2335
// if (endingPos < 0)
2333
2336
// {
2334
2337
// goto originalDoneLabel;
2335
2338
// }
2336
- Ldloc ( runtextLocal ) ;
2337
- Ldc ( subsequentCharacter ) ;
2338
- Ldloc ( endingPos ) ;
2339
- Ldc ( 1 ) ;
2340
- Sub ( ) ;
2339
+ Ldloca ( runtextSpanLocal ) ;
2340
+ Ldloc ( startingPos ) ;
2341
2341
Ldloc ( endingPos ) ;
2342
2342
Ldloc ( startingPos ) ;
2343
2343
Sub ( ) ;
2344
- Call ( s_stringLastIndexOfCharIntInt ) ;
2344
+ Call ( s_spanSliceIntIntMethod ) ;
2345
+ Ldc ( subsequentCharacter ) ;
2346
+ Call ( s_spanLastIndexOfChar ) ;
2345
2347
Stloc ( endingPos ) ;
2346
2348
Ldloc ( endingPos ) ;
2347
2349
Ldc ( 0 ) ;
2348
2350
BltFar ( originalDoneLabel ) ;
2351
+
2352
+ // endingPos += startingPos;
2353
+ Ldloc ( endingPos ) ;
2354
+ Ldloc ( startingPos ) ;
2355
+ Add ( ) ;
2356
+ Stloc ( endingPos ) ;
2349
2357
}
2350
2358
else
2351
2359
{
0 commit comments