Skip to content

Commit d4c7d86

Browse files
authoredJan 27, 2025··
Another attempt at fixing #99198 (#111255)
The problem was always `// Note: We don't set the IsUnboxingStub flag on template methods (all template lookups performed at runtime are performed with this flag not set`, I tried working around it in the original fix, but looks like I actually need the function pointer in #111178 (the tests are not failing but I have a local test that does). So trying an alternative approach that just deletes the weird code. It's possible this only had to be weird due to universal shared code.
1 parent 5c831a4 commit d4c7d86

File tree

3 files changed

+36
-25
lines changed

3 files changed

+36
-25
lines changed
 

‎src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs

+11-7
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,11 @@ internal void ParseNativeLayoutInfo(InstantiatedMethod method)
296296

297297
InstantiatedMethod nonTemplateMethod = method;
298298

299-
// Templates are always non-unboxing stubs
300-
if (method.UnboxingStub)
299+
// Templates are always unboxing stubs for valuetype instance methods
300+
if (!method.UnboxingStub && method.OwningType.IsValueType && !TypeLoaderEnvironment.IsStaticMethodSignature(method.NameAndSignature))
301301
{
302-
// Strip unboxing stub, note the first parameter which is false
303-
nonTemplateMethod = (InstantiatedMethod)method.Context.ResolveGenericMethodInstantiation(false, (DefType)method.OwningType, method.NameAndSignature, method.Instantiation);
302+
// Make it an unboxing stub, note the first parameter which is true
303+
nonTemplateMethod = (InstantiatedMethod)method.Context.ResolveGenericMethodInstantiation(true, (DefType)method.OwningType, method.NameAndSignature, method.Instantiation);
304304
}
305305

306306
uint nativeLayoutInfoToken;
@@ -311,11 +311,15 @@ internal void ParseNativeLayoutInfo(InstantiatedMethod method)
311311
throw new MissingTemplateException();
312312
}
313313

314-
// We might have a mismatch between unboxing/non-unboxing variants so only remember it for static methods
315-
if (TypeLoaderEnvironment.IsStaticMethodSignature(templateMethod.NameAndSignature)
316-
&& templateMethod.FunctionPointer != IntPtr.Zero)
314+
if (templateMethod.FunctionPointer != IntPtr.Zero)
317315
{
318316
nonTemplateMethod.SetFunctionPointer(templateMethod.FunctionPointer);
317+
318+
// Compensate for the template being an unboxing stub
319+
if (nonTemplateMethod != method)
320+
{
321+
method.SetFunctionPointer(TypeLoaderEnvironment.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(templateMethod.FunctionPointer, templateMethod.OwningType.RuntimeTypeHandle));
322+
}
319323
}
320324

321325
// Ensure that if this method is non-shareable from a normal canonical perspective, then

‎src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,17 @@ public bool TryGetGenericVirtualMethodPointer(InstantiatedMethod method, out Int
258258
}
259259
}
260260

261+
InstantiatedMethod nonTemplateMethod = method;
262+
263+
// Templates are always unboxing stubs for valuetype instance methods
264+
if (!method.UnboxingStub && method.OwningType.IsValueType && !IsStaticMethodSignature(method.NameAndSignature))
265+
{
266+
// Make it an unboxing stub, note the first parameter which is true
267+
nonTemplateMethod = (InstantiatedMethod)method.Context.ResolveGenericMethodInstantiation(true, (DefType)method.OwningType, method.NameAndSignature, method.Instantiation);
268+
}
269+
261270
// If we cannot find an exact method entry point, look for an equivalent template and compute the generic dictionary
262-
InstantiatedMethod templateMethod = TemplateLocator.TryGetGenericMethodTemplate(method, out _, out _);
271+
InstantiatedMethod templateMethod = TemplateLocator.TryGetGenericMethodTemplate(nonTemplateMethod, out _, out _);
263272
if (templateMethod == null)
264273
{
265274
methodPointer = default;

‎src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs

+15-17
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ public enum MethodEntryFlags
107107

108108
public MethodDesc Method => _method;
109109

110+
public virtual bool IsUnboxingStub => _method.OwningType.IsValueType && !_method.Signature.IsStatic;
111+
110112
public NativeLayoutMethodEntryVertexNode(NodeFactory factory, MethodDesc method, MethodEntryFlags flags)
111113
{
112114
_method = method;
@@ -148,7 +150,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
148150

149151
if ((_flags & MethodEntryFlags.SaveEntryPoint) != 0)
150152
{
151-
IMethodNode methodEntryPointNode = GetMethodEntrypointNode(context, out _);
153+
IMethodNode methodEntryPointNode = GetMethodEntrypointNode(context);
152154
dependencies.Add(new DependencyListEntry(methodEntryPointNode, "NativeLayoutMethodEntryVertexNode entrypoint"));
153155
}
154156

@@ -187,17 +189,17 @@ public override Vertex WriteVertex(NodeFactory factory)
187189
}
188190
}
189191

192+
if (IsUnboxingStub)
193+
flags |= MethodFlags.IsUnboxingStub;
194+
190195
uint fptrReferenceId = 0;
191196
if ((_flags & MethodEntryFlags.SaveEntryPoint) != 0)
192197
{
193198
flags |= MethodFlags.HasFunctionPointer;
194199

195-
bool unboxingStub;
196-
IMethodNode methodEntryPointNode = GetMethodEntrypointNode(factory, out unboxingStub);
200+
IMethodNode methodEntryPointNode = GetMethodEntrypointNode(factory);
197201
fptrReferenceId = factory.MetadataManager.NativeLayoutInfo.ExternalReferences.GetIndex(methodEntryPointNode);
198202

199-
if (unboxingStub)
200-
flags |= MethodFlags.IsUnboxingStub;
201203
if (methodEntryPointNode.Method.IsCanonicalMethod(CanonicalFormKind.Universal))
202204
flags |= MethodFlags.FunctionPointerIsUSG;
203205
}
@@ -219,10 +221,9 @@ private Vertex GetContainingTypeVertex(NodeFactory factory)
219221
}
220222
}
221223

222-
protected virtual IMethodNode GetMethodEntrypointNode(NodeFactory factory, out bool unboxingStub)
224+
protected virtual IMethodNode GetMethodEntrypointNode(NodeFactory factory)
223225
{
224-
unboxingStub = _method.OwningType.IsValueType && !_method.Signature.IsStatic;
225-
IMethodNode methodEntryPointNode = factory.MethodEntrypoint(_method, unboxingStub);
226+
IMethodNode methodEntryPointNode = factory.MethodEntrypoint(_method, IsUnboxingStub);
226227
return methodEntryPointNode;
227228
}
228229
}
@@ -748,15 +749,11 @@ public override Vertex WriteVertex(NodeFactory factory)
748749
return SetSavedVertex(factory.MetadataManager.NativeLayoutInfo.TemplatesSection.Place(methodEntryVertex));
749750
}
750751

751-
protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory, out bool unboxingStub)
752+
protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory)
752753
{
753754
Debug.Assert(NeedsEntrypoint(_method));
754-
unboxingStub = _method.OwningType.IsValueType && !_method.Signature.IsStatic;
755755
// TODO-SIZE: this is only address taken if it's a target of a delegate
756-
IMethodNode methodEntryPointNode = factory.AddressTakenMethodEntrypoint(_method, unboxingStub);
757-
// Note: We don't set the IsUnboxingStub flag on template methods (all template lookups performed at runtime are performed with this flag not set,
758-
// since it can't always be conveniently computed for a concrete method before looking up its template)
759-
unboxingStub = false;
756+
IMethodNode methodEntryPointNode = factory.AddressTakenMethodEntrypoint(_method, IsUnboxingStub);
760757
return methodEntryPointNode;
761758
}
762759

@@ -1677,7 +1674,7 @@ public WrappedMethodDictionaryVertexNode(NodeFactory factory, MethodDesc method)
16771674
{
16781675
}
16791676

1680-
protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory, out bool unboxingStub)
1677+
protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory)
16811678
{
16821679
throw new NotSupportedException();
16831680
}
@@ -1903,16 +1900,17 @@ private sealed class WrappedMethodEntryVertexNode : NativeLayoutMethodEntryVerte
19031900
public bool _unboxingStub;
19041901
public IMethodNode _functionPointerNode;
19051902

1903+
public override bool IsUnboxingStub => _unboxingStub;
1904+
19061905
public WrappedMethodEntryVertexNode(NodeFactory factory, MethodDesc method, bool unboxingStub, IMethodNode functionPointerNode) :
19071906
base(factory, method, functionPointerNode != null ? MethodEntryFlags.SaveEntryPoint : default(MethodEntryFlags))
19081907
{
19091908
_unboxingStub = unboxingStub;
19101909
_functionPointerNode = functionPointerNode;
19111910
}
19121911

1913-
protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory, out bool unboxingStub)
1912+
protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory)
19141913
{
1915-
unboxingStub = _unboxingStub;
19161914
return _functionPointerNode;
19171915
}
19181916

0 commit comments

Comments
 (0)
Please sign in to comment.