3 ms·
> The rest is handled by the compiler, instead of depending on the C calling convention, it can avoid having things in registers during yield. Yep, the frame p
by messe 1y ago
> The rest is handled by the compiler, instead of depending on the C calling convention, it can avoid having things in registers during yield.
Yep, the frame pointer as well if you're using it. This is exactly how its implemented in user-space in Zig's WIP std.Io branch green-threading implementation: https://github.com/ziglang/zig/blob/ce704963037fed60a30fd9d40114d0c899feee66/lib/std/Io/IoUring.zig#L607-L783 https://github.com/ziglang/zig/blob/ce704963037fed60a30fd9d4...
On ARM64, only fp, sp and pc are explicitly restored; and on x86_64 only rbp, rsp, and rip. For everything else, the compiler is just informed that the registers will be clobbered by the call, so it can optimize allocation to avoid having to save/restore them from the stack when it can.
- flimflamm 1y agoIs this just buttering the cost of switches by crippling the optimization options compiler have?
- lukaslalinsky 1y agoIf this was done the classical C way, you would always have to stack-save a number of registers, even if they are not really needed. The only difference here is that the compiler will do the save for you, in whatever way fits the context best. Sometimes it will stack-save, sometimes it will decide to use a different option. It's always strictly better than explicitly saving/restoring N registers unaware of the context. Keep in mind, that in Zig, the compiler always knows the entire code base. It does not work on object/function boundaries. That leads to better optimizations.
- hawk_ 1y agoThis is amazing to me that you can do this in Zig code directly as opposed to messing with the compiler.
- messe 1y agoTo be fair, this can be done in GNU C as well. Like the Zig implementation, you'd still have to use inline assembly.
- hawk_ 1y ago> If this was done the classical C way, you would always have to stack-save a number of registers I see, so you're saying that GCC can be coaxed into gathering only the relevant registers to stack and unstack not blindly do all of them?
- messe 1y agoYes, you write inline assembly that saves the frame pointer, stack pointer, and instruction pointer to the stack, and list every other register as a clobber. GCC will know which ones its using at the call-site (assuming the function gets inlined; this is more likely in Zig due to its single unit of compilation model), and save those to the stack. If it doesn't get inlined, it'll be treated as any other C function and only save the ones needed to be preserved by the target ABI.
- lukaslalinsky 1y agoSee https://github.com/alibaba/PhotonLibOS/blob/2fb4e979a4913e684404e6996970b679c3e4c73f/thread/thread.cpp#L931 https://github.com/alibaba/PhotonLibOS/blob/2fb4e979a4913e68... for GNU C++ example. It's a tiny bit more limited, because of how the compilation works, but the concept is the same.
- hawk_ 1y agoWhat do you mean by "buttering the cost of switches", can you elaborate? (I am trying to learn about this topic)
- masfuerte 1y agoI think it is > buttering the cost of switches [over the whole execution time] The switches get cheaper but the rest of the code gets slower (because it has less flexibility in register allocation) so the cost of the switches is "buttered" (i.e. smeared) over the rest of the execution time. But I don't think this argument holds water. The surrounding code can use whatever registers it wants. In the worst case it saves and restores all of them, which is what a standard context switch does anyway. In other words, this can be better and is never worse.
- GoblinSlayer 1y agoI wonder how you see it. Stackful coroutines switch context on syscall in the top stack frame, the deeper frames are regular optimized code, but syscall/sysret is already big context switch. And read/epoll loop has exactly same structure, the point of async programming isn't optimization of computation, but optimization of memory consumption. Performance is determined by features and design (and Electron).