-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
Labels
Description
Based on a discussion in the open PR, when an intrinsic is JIT'd an AV occurs later in CEEInfo::getArgType when it calls GetModule(sig->scope)
which calls GetDynamicResolver(scope)->GetDynamicMethod().
This is a random exception, and only occurs in a release (or checked) build of the runtime when R2R is used on S.P.Corelib. Setting "dotnet_readytorun" to 0
prevents the exception. So when the JIT compiler decides to JIT the intrinsic method that was compiled for R2R, it causes the AV.
Repro:
- Clone the PR referenced above
- Change the class
InstanceCalliHelper
in filesrc\coreclr\System.Private.CoreLib\src\System\Reflection\InstanceCalliHelper.cs
so that every[MethodImpl(MethodImplOptions.NoInlining)]
is replaced with[MethodImpl(MethodImplOptions.AggressiveInlining)]
- Build runtime in release or checked.
- Run the test System.Reflection.Tests.MethodInfoTests.TestProperties
- You may want to put a breakpoint in
MethodDesc::GenerateFunctionPointerCall(DynamicResolver** resolver, COR_ILMETHOD_DECODER** methodILDecoder)
(fileinstancecaii.cpp
) to encourage the timing necessary to repro. - Run this a few times until the failure occurs. If the breakpoint is hit in the step above, the exception should occur afterwards.
Sample repro:
cd C:\git\YOURREPO\artifacts\bin\System.Reflection.Tests\Release\net10.0
C:\git\YOURREPO\artifacts\bin\testhost\net10.0-windows-Release-x64\dotnet.exe exec --runtimeconfig System.Reflection.Tests.runtimeconfig.json c:\Users\YOURALIAS\.nuget\packages\microsoft.dotnet.xunitconsolerunner\2.9.0-beta.24475.5\tools\net9.0\xunit.console.dll System.Reflection.Tests.dll -method System.Reflection.Tests.MethodInfoTests.TestProperties
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
steveharter commentedon May 12, 2025
The AV is occurring because
sig->scope
is pointing to memory that has been freed. The scope (which contains the new signature containing the function pointer signature with(HasThis|ExplicitThis)
was freed because the intrinsic has been jitted and the corresponding 'scope" was freed in TransientMethodDetails::~TransientMethodDetails().@AaronRobinsonMSFT the scope containing the dynamic method also contains its own definition of a function pointer, but after being jitted, the scope\context containing that function pointer signature is deleted. Do we have any other cases of an intrinsic that defines its own signatures? Is it OK to tell the jitter not to inline these intrinsics?
Full call stack:
dotnet-policy-service commentedon May 13, 2025
Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.
AaronRobinsonMSFT commentedon May 13, 2025
Not that I am aware of.
That would be less than ideal. I could be missing something here, but my assumption is that the generated code and signatures exists only during the JIT and then can be freed. The transient function system assumes that the functions are small enough that we can just regenerate them on demand. Since R2R is inovlved, perhaps there might be something we need to add to R2R?
Why is this needed after jitting?
steveharter commentedon May 13, 2025
After a further look, this needs to be fixed.
The callstack shared earlier with
TransientMethodDetails::~TransientMethodDetails()
is a few frames afterMethodDesc::GenerateFunctionPointerCall()
returns (which creates the stub intrinsic).AaronRobinsonMSFT commentedon May 13, 2025
I also think that
fILIntrinsic
might need to be set totrue
.steveharter commentedon May 16, 2025
FWIW, the ILStubLinker use in https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/instancecalli.cpp#L29 could just pass in
NULL
instead ofthis
and the call toSetSubMethodDesc()
isn't necessary. We don't really have a "stub" that needs to call the method, we want to replace the method.