Skip to content

Commit c33f7bd

Browse files
committed
Remove generated locals in RegexCompiler.LoadSearchValues
Rely instead of improvements to JIT's recognition of Unsafe.As.
1 parent 0b5f137 commit c33f7bd

File tree

1 file changed

+10
-4
lines changed
  • src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions

1 file changed

+10
-4
lines changed

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ internal abstract class RegexCompiler
100100
private static readonly MethodInfo s_arrayResize = typeof(Array).GetMethod("Resize")!.MakeGenericMethod(typeof(int));
101101
private static readonly MethodInfo s_mathMinIntInt = typeof(Math).GetMethod("Min", new Type[] { typeof(int), typeof(int) })!;
102102
private static readonly MethodInfo s_memoryMarshalGetArrayDataReferenceSearchValues = typeof(MemoryMarshal).GetMethod("GetArrayDataReference", new Type[] { Type.MakeGenericMethodParameter(0).MakeArrayType() })!.MakeGenericMethod(typeof(SearchValues<char>))!;
103+
private static readonly MethodInfo s_unsafeAs = typeof(Unsafe).GetMethod("As", new Type[] { typeof(object) })!;
103104
// Note:
104105
// Single-range helpers like IsAsciiLetterLower, IsAsciiLetterUpper, IsAsciiDigit, and IsBetween aren't used here, as the IL generated for those
105106
// single-range checks is as cheap as the method call, and there's no readability issue as with the source generator.
@@ -6117,16 +6118,21 @@ private void LoadSearchValues(ReadOnlySpan<char> chars)
61176118
// Logically do _searchValues[index], but avoid the bounds check on accessing the array,
61186119
// and cast to the known derived sealed type to enable devirtualization.
61196120

6120-
// DerivedSearchValues d = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(this._searchValues), index);
6121+
// DerivedSearchValues d = Unsafe.As<DerivedSearchValues>(Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(this._searchValues), index));
61216122
// ... = d;
61226123
Ldthisfld(s_searchValuesArrayField);
61236124
Call(s_memoryMarshalGetArrayDataReferenceSearchValues);
61246125
Ldc(index * IntPtr.Size);
61256126
Add();
61266127
_ilg!.Emit(OpCodes.Ldind_Ref);
6127-
LocalBuilder ioavLocal = _ilg!.DeclareLocal(list[index].GetType());
6128-
Stloc(ioavLocal);
6129-
Ldloc(ioavLocal);
6128+
Call(MakeUnsafeAs(list[index].GetType())); // provide JIT with details necessary to devirtualize calls on this instance
6129+
6130+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification =
6131+
"Calling Unsafe.As<T> is safe since the T doesn't have trimming annotations.")]
6132+
static MethodInfo MakeUnsafeAs(Type type)
6133+
{
6134+
return s_unsafeAs.MakeGenericMethod(type);
6135+
}
61306136
}
61316137
}
61326138
}

0 commit comments

Comments
 (0)