-
Notifications
You must be signed in to change notification settings - Fork 5.1k
NativeAOT: devirtualize isinst/castclass for monomorphic cases #80831
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
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch, @kunalspathak Issue DetailsCloses #80828 Luckily, we already have JIT-EE API to get exact list of implementations/subclasses for given type. interface IMyInterface{} // this interface has a single implementation
class Program : IMyInterface
{
static void Main()
{
Case1(new Program());
Case2(new Program());
}
[MethodImpl(MethodImplOptions.NoInlining)]
static bool Case1(object o) => o is IMyInterface;
[MethodImpl(MethodImplOptions.NoInlining)]
static IMyInterface Case2(object o) => (IMyInterface)o;
} Previous NativeAOT codegen:; Method Program:Case1(System.Object):bool
sub rsp, 40
mov rdx, rcx
lea rcx, [(reloc)]
call CORINFO_HELP_ISINSTANCEOFINTERFACE
test rax, rax
setne al
movzx rax, al
add rsp, 40
ret
; Total bytes of code: 33
; Method Program:Case2(System.Object):IMyInterface
sub rsp, 40
mov rdx, rcx
lea rcx, [(reloc)]
call CORINFO_HELP_CHKCASTINTERFACE
nop
add rsp, 40
ret
; Total bytes of code: 25 New NativeAOT codegen:; Method Program:Case1(System.Object):bool
test rcx, rcx
je SHORT G_M13626_IG05
lea rax, [(reloc)]
cmp qword ptr [rcx], rax
je SHORT G_M13626_IG05
xor rcx, rcx
G_M13626_IG05:
xor eax, eax
test rcx, rcx
setne al
ret
; Total bytes of code: 28
; Method Program:Case2(System.Object):IMyInterface
sub rsp, 40
mov rdx, rcx
mov rax, rdx
test rax, rax
je SHORT G_M12806_IG05
lea rcx, [(reloc)]
cmp qword ptr [rax], rcx
je SHORT G_M12806_IG05
mov rcx, qword ptr [rsp+20H]
call CORINFO_HELP_CHKCASTINTERFACE ;; this is used to throw InvalidCastException only
G_M12806_IG05:
nop
add rsp, 40
ret
; Total bytes of code: 43
|
Is |
The code is bigger but should also be faster, since we will rarely need to call the helper (only if the cast will throw). Though I'm not quite sure why we're shuffling those registers about like we do... |
Curious: if we had hot/cold splitting support in NativeAOT (#77583), would that place the |
if (this->IsTargetAbi(CORINFO_NATIVEAOT_ABI) && | ||
((helper == CORINFO_HELP_ISINSTANCEOFINTERFACE) || (helper == CORINFO_HELP_CHKCASTINTERFACE)) && | ||
(info.compCompHnd->getExactClasses(pResolvedToken->hClass, 1, &actualImplCls) == 1) && | ||
(actualImplCls != NO_CLASS_HANDLE) && impIsClassExact(actualImplCls)) |
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.
Is there any reason this optimization shouldn't kick in for any other potential EE that returns 1 from getExactClasses
?
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 purely throughput reasons - 2 ifs + non inlined call getExactClasses
since I don't think it will be useful outside of NativeAOT anytime soon 🙂
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.
Seems a bit premature? If I remove the NAOT check and hack SPMI to always return 0
on replay of getExactClasses
I see no significant TP differences. IMO, as the general rule (no need to change this now) we should not be sacrificing abstractions unless they have demonstrable impact.
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.
no strong opinion on that, will remove as part of some next PR
It doesn't look like it's handled in hot/cold splitting now, but at least it's still considered as "cold" in jit |
Closes #80828
Luckily, we already have JIT-EE API to get exact list of implementations/subclasses for given type.
Previous NativeAOT codegen:
New NativeAOT codegen: