assembly - 为什么取消引用 `Arc<T> where T : MyTrait` 对齐到 0x10?

标签 assembly rust x86-64 micro-optimization

我对我的库进行了过度微优化,我正在查看生成的 ASM。我注意到调用 Arc<T> where T : MyTrait 的方法产生一些我认为正在对齐存储在 ArcInner 中的指针的东西到 0x10。

我用这段代码复制了它:

#![feature(test)]
extern crate test;

use std::sync::Arc;

struct DA;

trait Drain {
    fn log(&self, &DA);
}

struct BlackBoxDrain;

impl Drain for BlackBoxDrain {
    fn log(&self, da: &DA) {
        test::black_box::<&DA>(da);
    }
}

fn f(d: Arc<Drain>) {
    d.log(&DA)
}

fn main() {
    let arc_d = Arc::new(BlackBoxDrain);
    f(arc_d);
}

Rust playground (设置Nightly + Release 点击ASM)

有问题的 ASM 代码是:

movq    16(%r15), %rdi
leaq    15(%rdi), %rax
negq    %rdi
andq    %rax, %rdi
addq    %r14, %rdi

重要的是这个操作要尽可能快。由于 ASM 取消引用是 5 条指令,其中 3 条似乎可能是不必要的,所以我想了解为什么会发生这种情况以及是否可以提供帮助。也许我只是不明白这里的汇编指令。

编辑:我的最小示例并不完全相同,因为它看起来需要 crate 边界来防止编译器/链接器优化该序列。但在我的例子中,顺序完全相同,在一个紧密的(rust bench)循环中,没有涉及析构函数:只有一个方法调用 Arc<TraitObject> .

最佳答案

感谢 Chris Emerson 的回答,我意识到它与 vtable 和对齐规则有关。然后我在 Mozilla 的 Rust IRC channel 上四处询问,aatch 和 talchas 弄明白了:

rustc将始终计算存储在 T 中的数据( ArcInner<T> )的对齐偏移量- 因为每个 struct 可能不同实现 T .这没什么大不了的 - 因为这些指令非常快,并且会受到良好指令级 CPU 并行化的影响。

关于assembly - 为什么取消引用 `Arc<T> where T : MyTrait` 对齐到 0x10?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42332615/

相关文章:

assembly - PIC 是否处理不可屏蔽中断?

assembly - 清除 1 条 ARM 指令中的高 16 位

rust - 为什么在 String 上调用 .to_string() 可以避免移动错误?不是空投吗?

c - 读取另一个线程的寄存器或线程局部变量

assembly - 如何将负整数转换为字符串并在 MASM Assembly 中输出

assembly - 如何在Z80 ASM中重复将两个字节写入RAM block

unicode - 如何检测非规范化的 unicode 字符?

random - 从时间戳生成确定性随机数

gcc - 我应该如何让 gcc 在进入函数的过程中将堆栈指针重新对齐到 16 字节边界?

linux - 访问位置独立代码中的 .data 部分