Repository navigation
Consider that retbuf arg can point to GC heap in fgCreateCallDispatcherAndGetResult() - #39815
Conversation
|
@erozenfeld PTAL |
This reverts commit 8e7b5ae.
…C heap in fgCreateCallDispatcherAndGetResult in morph.cpp
erozenfeld
left a comment
There was a problem hiding this comment.
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.
@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.
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 structureSis a value type with non-GC fields and has such size that the result values ofCalleeandCallermust passed via return buffer;Calleeis transformed to tail call with helpers;Calleris invoked via Reflection.JIT will transform
Calleraccording to https://github.com/dotnet/runtime/blob/master/docs/design/features/tailcalls-with-helpers.md toDispatchTailCallsexpectsresultto be a pointer on the stack.However, during reflection call the return buffer for
Svalue 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
CallerandCalleeboth 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
DispatchTailCallsthe object corresponding to the return value buffer can be moved but pointers passed toDispatchTailCallswill not be update that leads toCalleeusing the old non-updated location when writing the return value.Solution: JIT needs to account for
IsStructRequiringStackAllocRetBufinfgCreateCallDispatcherAndGetResultin the similar way as it is done infgMorphCallinruntime/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!