-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
JIT: Update class for Unsafe.As<>() #85954
Conversation
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsWe used to import Closes #84377 (cc @stephentoub) public class ClassA
{
public virtual int GetVal() => 1;
}
public sealed class ClassB : ClassA
{
public override int GetVal() => 42;
}
void GetValUnsafe(ClassA tc) => Unsafe.As<ClassB>(tc).GetVal(); Old codegen: ; Method GetValUnsafe(ClassA):this
sub rsp, 40
mov rcx, rdx
mov rax, qword ptr [rdx]
mov rax, qword ptr [rax+48H]
call [rax+20H]ClassA:GetVal():int:this
nop
add rsp, 40
ret
; Total bytes of code: 23 New codegen: ; Method GetValUnsafe(ClassB):this
cmp byte ptr [rdx], dl
ret
; Total bytes of code: 3
|
src/coreclr/jit/importercalls.cpp
Outdated
{ | ||
CORINFO_GENERICHANDLE_RESULT embedInfo; | ||
info.compCompHnd->embedGenericHandle(pResolvedToken, false, &embedInfo); | ||
if (!embedInfo.lookup.lookupKind.needsRuntimeLookup) |
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 think you want to check for CORINFO_FLG_SHAREDINST
flag here.
I do not think you need to re-resolve the signature when it is not shared. sig->sigInst.methInst[0]
should have the exact type for the non-shared case.
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 do not think you need to re-resolve the signature when it is not shared. sig->sigInst.methInst[0] should have the exact type for the non-shared case.
Thanks, I was wondering about that too. I though that since I only need it here I can request that on demand, will change the original sig.
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.
@jkotas it seems that we're losing the exact sig due to this line of getCallInfo
:
runtime/src/coreclr/vm/jitinterface.cpp
Line 5232 in 231314d
pTargetMD = pTargetMD->GetWrappedMethodDesc(); |
this wrapped pMD is then used for getMethodSigInternal
does it look correct to you?
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.
Myabe it should be here if (pTargetMD->IsWrapperStub())
?
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.
Does it work with the last update, or do you still need help with this?
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.
Does it work with the last update, or do you still need help with this?
Still need help, the current impl doesn't work since we always have System._Canon as methodInst[0], I just prepared the code to pick up a fix in the getCallInfo
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.
getCallInfo
implementation is correct. getCallInfo
returns information about how the method should be called. Unsafe.As<object>
should be called as Unsafe.As<Canon>
with hidden argument, so it is that's what getCallInfo
returns, including signature for Unsafe.As<Canon>
. "Fixing" getCallInfo
to return some kind of different signature would require reviewing all places that use the signature returned by getCallInfo
and making sure that they behave correctly.
I think you want to take the method handle from CORINFO_RESOLVED_TOKEN
and call getMethodSig
on that. It should return what you are looking for.
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.
Ah I see, thanks! I assume we only need to do that for Unsafe.As
?
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.
Ah I see, thanks! I assume we only need to do that for Unsafe.As?
Yes - to fix the issues that you have linked.
A similar approach can be probably used to improve the type precision in other places, but that can be left for future.
src/coreclr/jit/importercalls.cpp
Outdated
const CORINFO_CLASS_HANDLE inst = sig->sigInst.methInst[0]; | ||
assert(inst != nullptr); | ||
|
||
if ((info.compCompHnd->getClassAttribs(inst) & CORINFO_FLG_SHAREDINST) == 0) |
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.
This is going to make us skip e.g. Unsafe.As<List<Canon>>
. We do not want that.
Delete this early out and just depend on isMoreSpecificType
to see whether the type is more exact.
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.
Thanks, addressed
Failure is #35066 |
We used to import
T Unsafe.As<T>(object o) where T : class
as a no-op and didn't benefit from a more exactT
hint.Closes #84377 (cc @stephentoub)
Closes #85906 (cc @MichalStrehovsky) - checked that it also devirtualizes the interface call
Old codegen:
New codegen: