4 ms·
As someone who works with QEMU, I must say QEMU is a shining example of how to do object oriented programming in C. That said, trying to follow the QEMU code u
by vegetablepotpie 4y ago
As someone who works with QEMU, I must say QEMU is a shining example of how to do object oriented programming in C.
That said, trying to follow the QEMU code using static analysis is impossible. Every function call is a function pointer stored as a parameter in a struct that was set up by a macro called in initialization. The only way I could figure out how things are tied together is with GDB.
I feel like using C++ would have been a better language choice.
- beagle3 4y agoThe modern QEMU is magic, but I find the original QEMU even more magical: It did not contain any assembly, and was easily portable to new architectures while still providing (relatively) decent performance -- the new TCG backend delivers much beter performance, at the cost of requiring more porting work for new host architectures. The original QEMU had an implementation of the required machine ops in C, but instead of calling those ops, it memcpy()d their implementation, thus enabling binary translation without interpreter overhead -- basically using the underlying "gcc" as a code-generator at runtime without including it. Pure elegance and/or madness. And it worked very well.
- versteegen 4y agoNice. Copying (concatenating) the opcode implementations into an executable memory buffer is well-known. There are variants but it seems to generally be called inline threading or dynamic superinstructions or the memcpy method [1]. If you can manage to do that in C (probably with the GCC computed-goto extension?) without asm or editing machine code I think it's a very good complexity-performance tradeoff, but unfortunately it doesn't seem to be too popular. It's faster than direct-threaded VMs but only eliminates one part of the instruction dispatch overhead compared to a real JIT (e.g. LuaJIT 2 vs LuaJIT 1) which loads operands directly or inlines them and does register allocation. But once you do inline threading, you have opportunities to eliminate more of the interpretation overhead, and the payoff becomes even greater e.g. [2]. [1] Markku Rossi, Kengatharan Sivalingam, 1996, A Survey of Instruction Dispatch Techniques for Byte-Code Interpreters, https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.9849 https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.... [2] M. Anton Ertl, David Gregg, 2004, Combining Stack Caching with Dynamic Superinstructions https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.90.4604&rep=rep1&type=pdf https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.90...