4 ms·
A very interesting article. One thing that stood out to me: > Unfortunately, Rust does not support [a save-all-registers calling convention]. It was proposed
by haberman 10y ago
A very interesting article. One thing that stood out to me:
> Unfortunately, Rust does not support [a save-all-registers calling convention]. It was proposed once, but did not get accepted for various reasons. The primary reason was that such calling conventions can be simulated by writing a naked wrapper function.
Followed by:
> However, auto-vectorization causes a problem for us: Most of the multimedia registers are caller-saved. [...] We don’t use any multimedia registers explicitly, but the Rust compiler might auto-vectorize our code (including the exception handlers).
This seems like a pretty convincing argument in favor of supporting this calling convention explicitly: only Rust knows what registers it is actually using. The current approach devolves into preserving every register that Rust might possibly use.
AVX-512 has 2kb of registers alone! That's a lot of junk to save to the stack on the off-chance that Rust decides to super-auto-vectorize something.
- pcwalton 10y ago> That's a lot of junk to save to the stack on the off-chance that Rust decides to super-auto-vectorize something. Note that LLVM loves to use the XMM registers to do memcpys. This is something that kernels definitely do. So it's definitely a tradeoff.
- amluto 10y agoUsing extended state (XMM, etc) in a kernel is asking for performance problems. Saving and restoring is quite slow, and manually saving just a couple of, say, XMM regs defeats the "init optimization".
- haberman 10y agoRight but my point is that saving registers that are not actually used is needless waste. If a "save all registers" calling convention was natively supported by Rust, you would only pay the cost for registers that are actually used.
- Manishearth 10y agoNot exactly, you would have to save all registers all the time. For caller-saved/scratch registers in interrupt handlers, not only do you have to avoid stomping over registers, anything you call has to do too. You have three options here: - Save all the registers in each interrupt - Only call "save all registers" functions in your function, enforce this somehow. Since things like pagefault handlers can get pretty involved, you probably don't want to do this. - Just compile your kernel with most extra registers disabled. There is the fourth option which involves whole program taint analysis or something to track the registers stomped on by all transitive calls from the exception handler. Requires special compiler support though.
- haberman 10y agoYou certainly wouldn't have to save all registers in the case of a leaf function. And yes, optimizing this would require special compiler support. That is the point! The compiler is the only component that is in a position to possibly do something smarter than spilling everything. Even if the compiler doesn't actually do this, letting users say what they mean is better than making them write something that will definitely be sub-optimal. It at least leaves open the possibility that the compiler could do something smarter.