Description
openedon Jan 10, 2023
Godbolt link: https://godbolt.org/z/YM65qf41h
I tried this simple custom DST method:
use std::any::TypeId;
use std::any::Any;
use std::hint::black_box;
struct A<T:?Sized+'static> {
a: i32,
b: T
}
impl<T:?Sized+'static> A<T> {
fn bb(&self) -> TypeId {
self.b.type_id()
}
}
pub fn main() {
let mut a0 = black_box(A{a: 8, b: 9 as i32});
let mut a: &mut A<dyn Any> = &mut a0;
a=black_box(a);
black_box(a.bb());
}
It turns out the generated assembly (rustc 1.68.0-nightly (659e169d3 2023-01-04) -Copt-level=3
) contains strange operations on the %rdi
register, while never actually using the %rdi
register. It doesn't seem to be performing any caller-reserving-space sort of stuff, and there doesn't seem to be the need for such behavior for this method.
<T as core::any::Any>::type_id:
movabs rax, 3735189839305137790
ret
core::ptr::drop_in_place<i32>:
ret
example::main:
push rbx
sub rsp, 32
movabs rax, 38654705672
mov qword ptr [rsp + 24], rax
lea rax, [rsp + 24]
mov qword ptr [rsp + 8], rax
lea rax, [rip + .L__unnamed_1]
mov qword ptr [rsp + 16], rax
lea rbx, [rsp + 8]
mov rax, qword ptr [rsp + 16]
# OPERATION ON RDI
mov rdi, qword ptr [rax + 16]
add rdi, 3
and rdi, -4
add rdi, qword ptr [rsp + 8]
# THE ACTUAL FUNCTION CALL
call qword ptr [rax + 24]
mov qword ptr [rsp + 8], rax
add rsp, 32
pop rbx
ret
.L__unnamed_1:
.quad core::ptr::drop_in_place<i32>
.asciz "\004\000\000\000\000\000\000\000\004\000\000\000\000\000\000"
.quad <T as core::any::Any>::type_id
If we re-implement it as a trait object method call, there won't be operations on %rdi register but rather a direct call.
I haven't tried with more complex code yet, but with simple methods, there seems to be a consistent pattern where custom DST produces longer code than a typical trait object.
Meta
rustc 1.68.0-nightly (659e169d3 2023-01-04)
:
Backtrace
<backtrace>