Ci sono parecchi casi in cui questo viene fatto. Non ho familiarità con l'implementazione di Jikes, ma ho letto sia su progetti basati su Java che su PyPy. La cosa che la maggior parte di loro ha in comune è la separazione delle cose in due livelli: livello runtime/interprete e livello applicazione. Ogni livello ha i propri oggetti, eccezioni, flusso di esecuzione, ecc.
Quando ci si pensa in modo astratto, in realtà è più facile da capire. Il livello di runtime potrebbe essere stato scritto in memoria o meno, a basso livello o ad alto livello, imperativo o funzionale. Questo non importa. Ciò che conta è la sua funzione, quello che fa. Alla fine viene tradotto in codice macchina e tutto il codice macchina è lo stesso di una macchina. Tale codice accetta opcode e dati come input, esegue azioni predefinite basate su tale, gestisce le risorse, ecc.
Il livello applicazione è contenuto in questi codici opzionali. Il livello dell'applicazione rappresenta un'altra funzione complessiva che accetta l'input, lo elabora ed esegue l'output. Questi passaggi potrebbero anche incorporare una routine di gestione della memoria. Il runtime non si preoccupa di ciò che fanno gli opcode finché sono validi e li esegue semplicemente. In teoria, puoi scrivere una lingua GC che contiene un linguaggio GC che contiene un linguaggio GC ... e così via fino a quando non raggiungi velocità ENIAC. ;)
Direi che il differenziatore in design come Jikes è la loro efficienza (e talvolta flessibilità). Non è sufficiente scrivere un GC, un interprete o un runtime in un linguaggio GC. Il risultato deve essere utilizzabile, il che significa spesso velocità. Potrebbe anche essere necessario adottare disposizioni per gestire l'integrazione del codice nativo a livello di applicazione. La maggior parte del vero lavoro va in quella roba. L'esecuzione di un GC in un linguaggio GC è la parte più semplice: fondamentalmente basta etichettare e gestire gli oggetti a diversi livelli di astrazione.
Nota: se si codifica il linguaggio GC e il runtime basato su GC, è possibile sfruttare questo vantaggio per prestazioni e semplicità. Ad esempio, invece di avere due interi garbage collector in esecuzione, uno sopra l'altro, puoi avere un GC più intelligente in basso con un GC sottile in cima. Il GC più intelligente conosce la differenza tra il runtime e il livello di applicazione, assicurandosi di operare su di essi separatamente e di non eseguire una miscelazione impropria. Il thin top GC essenzialmente fa semplicemente chiamate di routine al GC principale o etichetta oggetti in un modo che il GC principale comprende, ma questo non aggiunge un sacco di overhead.
La cosa su questo tipo di progetti è che ognuno è un po 'diverso. La natura del target e i linguaggi di implementazione dettano molto le scelte progettuali. Ti offre molte opportunità per essere creativo con il modo in cui risolvi il problema.
La vera risposta è nel codice sorgente ... quindi prendi il codice sorgente di Jikes e cerca all'interno di esso. –
L'ho fatto. È un progetto enorme, e non ho trovato rivelazioni specifiche. È come rispondere "come funziona la JVM" con "vai a scaricare il repository HotSpot e inizia a grepping!" –
Ho sentito parlare di MMTK e fondamentalmente si tratta di un generatore di programmi. Potresti anche leggere i loro articoli e chiedere agli autori ... –