Mi piacerebbe scrivere un piccolo compilatore JIT proof-of-concept per un elaboratore di linguaggio giocattolo che ho scritto (puramente accademico), ma ho qualche problema nelle altezze medie del design. Concettualmente, ho familiarità con il funzionamento di JIT - si compila bytecode in codice (macchina o assieme?) Da eseguire. Tuttavia, a livello di dadi e bulloni, non sono abbastanza avvincente con il come lo si fa effettivamente il facendo.Come generare ed eseguire il codice nativo in modo dinamico?
mio (molto "newb") reazione istintiva, dal momento che ho non è la prima idea da dove cominciare, sarebbe quello di provare qualcosa di simile al seguente:
- mmap() un blocco di memoria , modificando l'accesso a PROT_EXEC
- scrivere il codice nativo nel blocco
- negozio registri correnti (stack pointer, et al.) in qualche posto accogliente
- modificare i registri correnti a punto nel blocco di codice nativo nella regione mappata
- il codice nativo sarebbe ora ottenere eseguito dalla macchina
- ripristinare i precedenti registri
è che anche vicino ad un/l'algoritmo corretto? Ho provato a esaminare diversi progetti che so essere in possesso di compilatori JIT (come ad esempio V8) ma questi codici sono difficili da consumare a causa delle loro dimensioni e non ho idea di dove iniziare a cercare.
Probabilmente puoi semplificare ulteriormente le cose: spesso puoi semplicemente prendere l'indirizzo di partenza del tuo codice all'interno del blocco 'mmap''ed e lanciarlo su un puntatore a funzione. In tal caso, il codice dovrebbe salvare e ripristinare i propri registri e così via. Dovresti esaminare le convenzioni di chiamata nelle tue piattaforme ABI (Application Binary Interface) per esattamente ciò che devi salvare (e come ottenere argomenti dal codice C, chiamare le funzioni C, ecc.). –
Non che io abbia molta esperienza con questo, ma potresti provare a interpretare l'interprete python di PiPi. Ho esaminato l'interprete CPython ed è abbastanza buono da leggere. – Falmarri
Davvero una buona domanda Chris! – jweyrich