5 ms·
> But doesn't this mean that they are translating and running the JIT and the JIT is creating new executable x86 code which then also needs to be translated? Y
by underdeserver 6y ago
> But doesn't this mean that they are translating and running the JIT and the JIT is creating new executable x86 code which then also needs to be translated?
Yup.
> I'm a bit baffled as to how any of this can work properly, for example if my JIT is sampling instructions to determine when to optimize, does Rosetta need to reverse-translate the actual instruction pointer back to the original x86 code offset?
Well, not exactly. Let's take JS as an example. First of all, you're only sampling calls that are still in the native language, so your instruction pointer is in the emulated virtual machine itself anyway, which is agnostic to the CPU architecture. See [1] for where SpiderMonkey samples.
What happens then is that the engine sees a function being called many times, so the JIT compiler decides to compile a function; it compiles the function and writes the compiled function to memory, then overwrites that function's address with a native function pointer.
The easiest hook the OS has to this process is mprotect(2). In modern OSes, memory is generally either writable or executable, but not both; so if you want to compile and write, and then execute, you need to call mprotect() between those steps to set permissions.
Knowing that your binary is Rosetta'd, MacOS can assume your JIT code is also AMD64 and translate that page on the fly. All they have to do is make sure the virtual memory addresses are correct - to not mess up those function pointers.
They can either do it lazily, through a pagefault handler, or greedily when mprotect is called to add executable permissions to the JIT-allocated memory.
[1] https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JIT_Optimization_Strategies https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Sp...
- jeffbee 6y agoThe hard part seems to be metadata, or information about the program rather than the program itself. Rosetta will translate the program but it doesn't know about the metadata, so you have a referential integrity problem, seemingly. For example what is going to happen if a program running under Rosetta uses setitimer to deliver SIGPROF? What's in si_addr?
- underdeserver 6y agoYou'll still have the address of the fault in si_addr. Addresses are addresses, both in AMD64 and ARM64. What's the difference?
- jeffbee 6y agoMaybe I'm just imagining things, but if I have a map from PC to function or line and Rosetta rewrites all my functions then I have a problem unless the Rosetta output is by some miracle exactly the same length as the input.
- monocasa 6y agoThey can keep a translation table around for fixing up what were the original instruction addresses. I've done that for writing emulators before. It ends up looking like DWARF.
- saagarjha 6y ago> In modern OSes, memory is generally either writable or executable, but not both; so if you want to compile and write, and then execute, you need to call mprotect() between those steps to set permissions. mprotect is slow. High-performance JIT compilers on macOS usually map memory as RWX or mirror-map the same page as RW- and R-X from two virtual addresses.