Update: Wine's PE -> UNIX
The original analysis that was done with wine 7.22 is still mostly true and you should read it first. There were some interesting improvements since then though which I’ll update you on here.
(analysis of the state as of wine 8.5)
Syscall Performance Optimizations
That’s a small optimization that comes with 0aae4b05633c ("ntdll: Use ret
instead of jmp to return from syscall dispatchers.")
commit.
@gio julliard: What's the reason for 0aae4b056?
@julliard better performance
@gio Why does it give better performance?
@julliard basically having paired call/ret helps branch prediction
I find this article on branch prediction interesting.
Faster Unix Calls
The calls to the UNIX part of any given DLL used to go through the
special __wine_unix_call()
syscall:
syscall thunk → __wine_syscall_dispatcher() → __wine_unix_call() → unixlib
Since this is for wine-internal calls only we can optimize it by skipping some taks that are required only for a syscall. And this is exactly what has happened - there’s a new dedicated dispatcher.
Here’s the original MR, the commit that introduces x86_64 handler, and the commit that does the switch to use it.
If you look at the __wine_syscall_dispatcher()
and
__wine_unix_call()
we can see what can be skipped:
-
pushfq
, - saving the segment registers
cs
,ds
,es
,fs
,ss
,gs
, -
xsavec64
/xsave64
/fxsave64
- instead only some xmm registers are saved manually due to calling convention differences, - some extra register shuffling used, among other things, for the above,
- getting function pointer from the service descriptor table - we are not doing a syscall, instead we can do the unix call directly using the unix call table and index
There’s also a jump to __wine_syscall_dispatcher_return
if restore flags
indicate that a full thread context restoration is needed.