Skip to content

Commit 8f546b8

Browse files
committed
Use Spans on Compiler Go() methods
1 parent 00daa4d commit 8f546b8

File tree

1 file changed

+28
-20
lines changed
  • src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions

1 file changed

+28
-20
lines changed

src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,12 @@ internal abstract class RegexCompiler
4949
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));
5050
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));
5151
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));
5253
private static readonly MethodInfo s_spanSliceIntMethod = typeof(ReadOnlySpan<char>).GetMethod("Slice", new Type[] { typeof(int) })!;
5354
private static readonly MethodInfo s_spanSliceIntIntMethod = typeof(ReadOnlySpan<char>).GetMethod("Slice", new Type[] { typeof(int), typeof(int) })!;
5455
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));
5556
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) })!;
5757
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) })!;
5958
private static readonly MethodInfo s_textInfoToLowerMethod = typeof(TextInfo).GetMethod("ToLower", new Type[] { typeof(char) })!;
6059
private static readonly MethodInfo s_arrayResize = typeof(Array).GetMethod("Resize")!.MakeGenericMethod(typeof(int));
6160

@@ -889,7 +888,7 @@ protected void EmitGo()
889888
}
890889

891890
// Initialize the main locals used throughout the implementation.
892-
LocalBuilder runtextLocal = DeclareString();
891+
LocalBuilder runtextSpanLocal = DeclareReadOnlySpanChar();
893892
LocalBuilder originalruntextposLocal = DeclareInt32();
894893
LocalBuilder runtextposLocal = DeclareInt32();
895894
LocalBuilder textSpanLocal = DeclareReadOnlySpanChar();
@@ -905,9 +904,11 @@ protected void EmitGo()
905904
// CultureInfo culture = CultureInfo.CurrentCulture; // only if the whole expression or any subportion is ignoring case, and we're not using invariant
906905
InitializeCultureForGoIfNecessary();
907906

908-
// string runtext = this.runtext;
907+
// ReadOnlySpan<char> runtextSpan = this.runtext.AsSpan();
909908
// int runtextend = this.runtextend;
910-
Mvfldloc(s_runtextField, runtextLocal);
909+
Ldthisfld(s_runtextField);
910+
Call(s_stringAsSpanMethod);
911+
Stloc(runtextSpanLocal);
911912
Mvfldloc(s_runtextendField, runtextendLocal);
912913

913914
// int runtextpos = this.runtextpos;
@@ -996,13 +997,13 @@ protected void EmitGo()
996997
// Creates a span for runtext starting at runtextpos until this.runtextend.
997998
void LoadTextSpanLocal()
998999
{
999-
// textSpan = runtext.AsSpan(runtextpos, this.runtextend - runtextpos);
1000-
Ldloc(runtextLocal);
1000+
// textSpan = runtextSpan.Slice(runtextpos, this.runtextend - runtextpos);
1001+
Ldloca(runtextSpanLocal);
10011002
Ldloc(runtextposLocal);
10021003
Ldloc(runtextendLocal);
10031004
Ldloc(runtextposLocal);
10041005
Sub();
1005-
Call(s_stringAsSpanIntIntMethod);
1006+
Call(s_spanSliceIntIntMethod);
10061007
Stloc(textSpanLocal);
10071008
}
10081009

@@ -1292,12 +1293,13 @@ void EmitBackreference(RegexNode node)
12921293

12931294
MarkLabel(body);
12941295

1295-
// if (runtext[matchIndex + i] != textSpan[i]) goto doneLabel;
1296-
Ldloc(runtextLocal);
1296+
// if (runtextSpan[matchIndex + i] != textSpan[i]) goto doneLabel;
1297+
Ldloca(runtextSpanLocal);
12971298
Ldloc(matchIndex);
12981299
Ldloc(i);
12991300
Add();
1300-
Call(s_stringGetCharsMethod);
1301+
Call(s_spanGetItemMethod);
1302+
LdindU2();
13011303
if (IsCaseInsensitive(node))
13021304
{
13031305
CallToLower();
@@ -2092,11 +2094,12 @@ void EmitAnchors(RegexNode node)
20922094
Ldloc(runtextposLocal);
20932095
Ldthisfld(s_runtextbegField);
20942096
Ble(success);
2095-
Ldthisfld(s_runtextField);
2097+
Ldloca(runtextSpanLocal);
20962098
Ldloc(runtextposLocal);
20972099
Ldc(1);
20982100
Sub();
2099-
Call(s_stringGetCharsMethod);
2101+
Call(s_spanGetItemMethod);
2102+
LdindU2();
21002103
Ldc('\n');
21012104
BneFar(doneLabel);
21022105
MarkLabel(success);
@@ -2328,24 +2331,29 @@ void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitL
23282331

23292332
if (subsequent?.FindStartingCharacter() is char subsequentCharacter)
23302333
{
2331-
// endingPos = runtext.LastIndexOf(subsequentCharacter, endingPos - 1, endingPos - startingPos);
2334+
// endingPos = runtextSpan.Slice(startingPos, endingPos - startingPos).LastIndexOf(subsequentCharacter);
23322335
// if (endingPos < 0)
23332336
// {
23342337
// goto originalDoneLabel;
23352338
// }
2336-
Ldloc(runtextLocal);
2337-
Ldc(subsequentCharacter);
2338-
Ldloc(endingPos);
2339-
Ldc(1);
2340-
Sub();
2339+
Ldloca(runtextSpanLocal);
2340+
Ldloc(startingPos);
23412341
Ldloc(endingPos);
23422342
Ldloc(startingPos);
23432343
Sub();
2344-
Call(s_stringLastIndexOfCharIntInt);
2344+
Call(s_spanSliceIntIntMethod);
2345+
Ldc(subsequentCharacter);
2346+
Call(s_spanLastIndexOfChar);
23452347
Stloc(endingPos);
23462348
Ldloc(endingPos);
23472349
Ldc(0);
23482350
BltFar(originalDoneLabel);
2351+
2352+
// endingPos += startingPos;
2353+
Ldloc(endingPos);
2354+
Ldloc(startingPos);
2355+
Add();
2356+
Stloc(endingPos);
23492357
}
23502358
else
23512359
{

0 commit comments

Comments
 (0)