Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ReadOnlySpan<char> on RegexCompiled engine. #62245

Merged
merged 2 commits into from
Dec 2, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ internal abstract class RegexCompiler
private static readonly MethodInfo s_stringAsSpanMethod = typeof(MemoryExtensions).GetMethod("AsSpan", new Type[] { typeof(string) })!;
private static readonly MethodInfo s_stringAsSpanIntIntMethod = typeof(MemoryExtensions).GetMethod("AsSpan", new Type[] { typeof(string), typeof(int), typeof(int) })!;
private static readonly MethodInfo s_stringGetCharsMethod = typeof(string).GetMethod("get_Chars", new Type[] { typeof(int) })!;
private static readonly MethodInfo s_stringIndexOfCharInt = typeof(string).GetMethod("IndexOf", new Type[] { typeof(char), typeof(int) })!;
private static readonly MethodInfo s_stringLastIndexOfCharIntInt = typeof(string).GetMethod("LastIndexOf", new Type[] { typeof(char), typeof(int), typeof(int) })!;
private static readonly MethodInfo s_textInfoToLowerMethod = typeof(TextInfo).GetMethod("ToLower", new Type[] { typeof(char) })!;
private static readonly MethodInfo s_arrayResize = typeof(Array).GetMethod("Resize")!.MakeGenericMethod(typeof(int));
Expand All @@ -83,6 +82,7 @@ internal abstract class RegexCompiler
private LocalBuilder? _runtextendLocal;
private LocalBuilder? _runtextposLocal;
private LocalBuilder? _runtextLocal;
private LocalBuilder? _runtextSpanLocal;
private LocalBuilder? _runtrackposLocal;
private LocalBuilder? _runtrackLocal;
private LocalBuilder? _runstackposLocal;
Expand Down Expand Up @@ -927,7 +927,7 @@ protected void GenerateFindFirstChar()
{
_runtextbegLocal = DeclareInt32();
}
_runtextLocal = DeclareString();
_runtextSpanLocal = DeclareReadOnlySpanChar();
_textInfoLocal = null;
if ((_options & RegexOptions.CultureInvariant) == 0)
{
Expand All @@ -954,8 +954,12 @@ FindNextStartingPositionMode.LeadingSet_LeftToRight_CaseInsensitive or
// Load necessary locals
// int runtextpos = this.runtextpos;
// int runtextend = this.runtextend;
// ReadOnlySpan<char> runtextSpan = this.runtext.AsSpan();
Mvfldloc(s_runtextposField, _runtextposLocal);
Mvfldloc(s_runtextendField, _runtextendLocal);
Ldthisfld(s_runtextField);
Call(s_stringAsSpanMethod);
Stloc(_runtextSpanLocal);
if (_code.RightToLeft)
{
Mvfldloc(s_runtextbegField, _runtextbegLocal!);
Expand Down Expand Up @@ -1139,9 +1143,10 @@ bool GenerateAnchors()
Ldloc(_runtextposLocal);
Ldloc(_runtextendLocal);
Beq(l2);
Ldthisfld(s_runtextField);
Ldloca(_runtextSpanLocal);
Ldloc(_runtextposLocal);
Call(s_stringGetCharsMethod);
Call(s_spanGetItemMethod);
LdindU2();
Ldc('\n');
Beq(l2);
MarkLabel(l1);
Expand Down Expand Up @@ -1191,25 +1196,27 @@ bool GenerateAnchors()
Ldthisfld(s_runtextbegField);
Ble(atBeginningOfLine);

// ... && runtext[runtextpos - 1] != '\n') { ... }
Ldthisfld(s_runtextField);
// ... && runtextSpan[runtextpos - 1] != '\n') { ... }
Ldloca(_runtextSpanLocal);
Ldloc(_runtextposLocal);
Ldc(1);
Sub();
Call(s_stringGetCharsMethod);
Call(s_spanGetItemMethod);
LdindU2();
Ldc('\n');
Beq(atBeginningOfLine);

// int tmp = runtext.IndexOf('\n', runtextpos);
Ldthisfld(s_runtextField);
Ldc('\n');
// int tmp = runtextSpan.Slice(runtextpos).IndexOf('\n');
Ldloca(_runtextSpanLocal);
Ldloc(_runtextposLocal);
Call(s_stringIndexOfCharInt);
Call(s_spanSliceIntMethod);
Ldc('\n');
Call(s_spanIndexOfChar);
using (RentedLocalBuilder newlinePos = RentInt32Local())
{
Stloc(newlinePos);

// if (newlinePos == -1 || newlinePos + 1 > runtextend)
// if (newlinePos == -1 || newlinePos + runtextpos + 1 > runtextend)
// {
// runtextpos = runtextend;
// return false;
Expand All @@ -1218,13 +1225,17 @@ bool GenerateAnchors()
Ldc(-1);
Beq(returnFalse);
Ldloc(newlinePos);
Ldloc(_runtextposLocal);
Add();
Ldc(1);
Add();
Ldloc(_runtextendLocal);
Bgt(returnFalse);

// runtextpos = newlinePos + 1;
// runtextpos = newlinePos + runtextpos + 1;
Ldloc(newlinePos);
Ldloc(_runtextposLocal);
Add();
Ldc(1);
Add();
Stloc(_runtextposLocal);
Expand All @@ -1243,14 +1254,13 @@ void GenerateIndexOf_LeftToRight(string prefix)
{
using RentedLocalBuilder i = RentInt32Local();

// int i = runtext.AsSpan(runtextpos, runtextend - runtextpos).IndexOf(prefix);
Ldthis();
Ldfld(s_runtextField);
// int i = runtextSpan.Slice(runtextpos, runtextend - runtextpos).IndexOf(prefix);
Ldloca(_runtextSpanLocal);
Ldloc(_runtextposLocal);
Ldloc(_runtextendLocal);
Ldloc(_runtextposLocal);
Sub();
Call(s_stringAsSpanIntIntMethod);
Call(s_spanSliceIntIntMethod);
Ldstr(prefix);
Call(s_stringAsSpanMethod);
Call(s_spanIndexOfSpan);
Expand All @@ -1276,14 +1286,13 @@ void GenerateIndexOf_RightToLeft(string prefix)
{
using RentedLocalBuilder i = RentInt32Local();

// int i = runtext.AsSpan(runtextpos, runtextbeg, runtextpos - runtextbeg).LastIndexOf(prefix);
Ldthis();
Ldfld(s_runtextField);
// int i = runtextSpan.Slice(runtextbeg, runtextpos - runtextbeg).LastIndexOf(prefix);
Ldloca(_runtextSpanLocal);
Ldloc(_runtextbegLocal!);
Ldloc(_runtextposLocal);
Ldloc(_runtextbegLocal!);
Sub();
Call(s_stringAsSpanIntIntMethod);
Call(s_spanSliceIntIntMethod);
Ldstr(prefix);
Call(s_stringAsSpanMethod);
Call(s_spanLastIndexOfSpan);
Expand Down Expand Up @@ -1316,14 +1325,13 @@ void GenerateFixedSet_RightToLeft()

if (set.Chars is { Length: 1 } && !set.CaseInsensitive)
{
// int i = runtext.AsSpan(runtextpos, runtextbeg, runtextpos - runtextbeg).LastIndexOf(set.Chars[0]);
Ldthis();
Ldfld(s_runtextField);
// int i = runtextSpan.Slice(runtextbeg, runtextpos - runtextbeg).LastIndexOf(set.Chars[0]);
Ldloca(_runtextSpanLocal);
Ldloc(_runtextbegLocal!);
Ldloc(_runtextposLocal);
Ldloc(_runtextbegLocal!);
Sub();
Call(s_stringAsSpanIntIntMethod);
Call(s_spanSliceIntIntMethod);
Ldc(set.Chars[0]);
Call(s_spanLastIndexOfChar);
Stloc(i);
Expand Down Expand Up @@ -1351,20 +1359,19 @@ void GenerateFixedSet_RightToLeft()
Label increment = DefineLabel();
Label body = DefineLabel();

Mvfldloc(s_runtextField, _runtextLocal);

// for (int i = runtextpos - 1; ...
Ldloc(_runtextposLocal);
Ldc(1);
Sub();
Stloc(i);
BrFar(condition);

// if (MatchCharClass(runtext[i], set))
// if (MatchCharClass(runtextSpan[i], set))
MarkLabel(body);
Ldloc(_runtextLocal);
Ldloca(_runtextSpanLocal);
Ldloc(i);
Call(s_stringGetCharsMethod);
Call(s_spanGetItemMethod);
LdindU2();
EmitMatchCharacterClass(set.Set, set.CaseInsensitive);
Brfalse(increment);

Expand Down Expand Up @@ -1405,13 +1412,13 @@ void GenerateFixedSet_LeftToRight()
using RentedLocalBuilder iLocal = RentInt32Local();
using RentedLocalBuilder textSpanLocal = RentReadOnlySpanCharLocal();

// ReadOnlySpan<char> span = this.runtext.AsSpan(runtextpos, runtextend - runtextpos);
Ldthisfld(s_runtextField);
// ReadOnlySpan<char> span = runtextSpan.Slice(runtextpos, runtextend - runtextpos);
Ldloca(_runtextSpanLocal);
Ldloc(_runtextposLocal);
Ldloc(_runtextendLocal);
Ldloc(_runtextposLocal);
Sub();
Call(s_stringAsSpanIntIntMethod);
Call(s_spanSliceIntIntMethod);
Stloc(textSpanLocal);

// If we can use IndexOf{Any}, try to accelerate the skip loop via vectorization to match the first prefix.
Expand Down