Rust 如何调用 &dyn Fn?

rad*_*ong 6 compiler-construction assembly x86-64 rust

我有这个 Rust 函数:

pub fn abc(x: &dyn Fn()) {
    x()
}
Run Code Online (Sandbox Code Playgroud)

当我在Godbolt Compiler Explorer上使用 Rust 1.63.0 编译它时,我得到了生成的 x86-64 汇编代码:

example::abc:
        push    rax
        call    qword ptr [rsi + 40]
        pop     rax
        ret
Run Code Online (Sandbox Code Playgroud)

偏移量从哪里来40?我想对生成的汇编代码有一个基本的了解。

Cha*_*man 11

&dyn Fn存储为 (data, vtable) 对。虚函数表包含:

  1. 指向 的函数指针drop_in_place::<Type>,用于删除eg中的类型Box<dyn Trait>(函数指针大小,usize在x86上)。

  2. 数据大小 ( usize)。

  3. 数据的对齐方式 ( usize)。

  4. 指向特征方法的函数指针列表,包括超级特征。因为Fn他们是:

    1. FnOnce::call_once()
    2. FnMut::call_mut()
    3. Fn::call(),这就是我们在您的代码中调用的内容。

Fn::call()偏移量drop_in_place(8 字节)+ 大小(8 字节)+ 对齐方式(8 字节)+ call_once(8 字节)+ call_mut(8 字节)= 40 字节也是如此。

  • 而在x86-64 System V ABI中,一个16字节的对象在一对寄存器中传递,因此RDI=数据,RSI=vtable,已经在寄存器中准备通过vtable条目进行间接调用。 (4认同)