-
Notifications
You must be signed in to change notification settings - Fork 5k
Consider that retbuf arg can point to GC heap in fgCreateCallDispatcherAndGetResult() #39815
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
Conversation
src/tests/JIT/Regression/JitBlue/Runtime_39581/Runtime_39581.ilproj
Outdated
Show resolved
Hide resolved
@erozenfeld PTAL |
This reverts commit 8e7b5ae.
…C heap in fgCreateCallDispatcherAndGetResult in morph.cpp
src/tests/JIT/Regression/JitBlue/Runtime_39581/Runtime_39581.il
Outdated
Show resolved
Hide resolved
src/tests/JIT/Regression/JitBlue/Runtime_39581/Runtime_39581.il
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a few minor suggestions.
I don't think this needs to be a hard requirement, if the pointer can be a by-ref to GC heap then the mechanism could pass it through as such. |
@jakobbotsch I am not sure if making |
if (origCall->gtType != TYP_VOID) | ||
{ | ||
retVal = gtClone(retValArg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jakobbotsch Do you remember why this handling was needed here? I understand that on System-V the method that uses return buffer must return an address to the return buffer in rax at the end. But do we use the value in the caller somehow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if JIT uses the returned pointer, but even if not it is presumably necessary for reverse pinvoke.
This is already what the JIT does for functions with ret buffers so I just did the same.
All GCStress legs except win-arm64 are green with the change. The ones that failed in win-arm64 are due to #38518 |
I don't think one more interior pointer should move the needle much and it should simplify the JIT's handling of this. |
…erAndGetResult() (dotnet#39815) Caller return buffer argument can point to GC heap while DispatchTailCalls expects the return value argument to point to the stack. We should use a temporary stack allocated return buffer to hold the value during the dispatcher call and copy the value back to the caller return buffer after that.
The issue manifests themselves when
Callee()
andCaller()
have the following simple structureS
is a value type with non-GC fields and has such size that the result values ofCallee
andCaller
must passed via return buffer;Callee
is transformed to tail call with helpers;Caller
is invoked via Reflection.JIT will transform
Caller
according to https://github.com/dotnet/runtime/blob/master/docs/design/features/tailcalls-with-helpers.md toDispatchTailCalls
expectsresult
to be a pointer on the stack.However, during reflection call the return buffer for
S
value type can be placed on the GC heapruntime/src/coreclr/src/vm/reflectioninvocation.cpp
Lines 1123 to 1143 in 3665779
JIT makes a wrong assumption that if
Caller
andCallee
both have return buffer arguments it can be simple passed from the former to the latter inruntime/src/coreclr/src/jit/morph.cpp
Lines 7907 to 7920 in 3665779
As a consequence, when GC is called at
DispatchTailCalls
the object corresponding to the return value buffer can be moved but pointers passed toDispatchTailCalls
will not be update that leads toCallee
using the old non-updated location when writing the return value.Solution: JIT needs to account for
IsStructRequiringStackAllocRetBuf
infgCreateCallDispatcherAndGetResult
in the similar way as it is done infgMorphCall
inruntime/src/coreclr/src/jit/morph.cpp
Lines 8908 to 8919 in 3665779
Thanks @erozenfeld for help with identifying the place with wrong logic in
fgCreateCallDispatcherAndGetResult
!