L'Interprete
L'interprete è il motore di ogni Macchina Astratta, sia essa imperativa,
Il funzionamento dell'interprete è essenzialmente ciclico, ed è basato sul cosiddetto ciclo FETCH-EXECUTE. Per espletare tale ciclo, l'interprete si avvale di alcuni registri, fra i quali principalmente il registro PC ( Program Counter ): in ogni istante, esso punta al prossimo bytecode da eseguire all'interno del metodo corrente. L'informazione riguardo a quale sia il metodo corrente non è solo mantenuta implicitamente tramite il registro PC, ma anche esplicitamente per mezzo dei registri VARS e FRAME. Tali registri puntano a delle zone di memoria all'interno dello Stack, e più precisamente all'interno dello Stack Frame relativo al metodo corrente dove sono contenute delle informazioni inerenti al metodo ed alla classe in cui esso è stato definito. In particolare, tramite il registro VARS, l'interprete può accedere alle variabili locali e agli argomenti del metodo e tramite FRAME può risalire alle costanti in esso utilizzate. Una volta letta l'istruzione successiva, l'interprete stabilisce se è necessario prelevare dal flusso di bytecode anche degli operandi, ed eventualmente li acquisisce. Quindi determina quale sia il complesso di azioni da portare avanti consultando l'Instruction Set. Dall'architettura generale si vede che le varie operazioni possono essere classificate in vari gruppi: in particolare consideriamo le operazioni di JUMP e le operazioni aritmetico-logiche primitive.
La gestione delle costanti verrà vista nel seguito discutendo della Method Area e del Class Manager. Dal momento che l'interprete è la componete più importante della Macchina Astratta, la sua configurazione in un dato istante determina lo stato della macchina stessa. In dettaglio, lo stato della macchina dipende da:
Tale stato è normalmente soggetto a variazioni graduali, ma in caso di istruzioni di tipo INVOKE, che invocano l'esecuzione di un nuovo metodo, il cambiamento è radicale ed è necessario tenere traccia dello stato prima dell'invocazione per poter riprendere dal punto corretto al termine del nuovo metodo. Di tale problematica si occupa lo Stack Manager. Le interazioni dell'interprete con le altri parti del sistema verranno esaminate in seguito. Si noti tuttavia che l'iniziativa di tutte le azioni è sempre dell'interprete, mentre gli altri moduli rispondono soltanto a richieste effettuate da questi, secondo una modalità di tipo MASTER/SLAVE. Pertanto l'architettura della macchina avrebbe potuto prevedere un interprete monolitico a diretto contatto con Stack, Heap, Method Area e Class Repository; di contro, la decisione di distribuire i compiti su più moduli è una scelta di design, che consente di dare un'idea abbastanza precisa del funzionamento della macchina, tramite l'analisi del protocollo di comunicazione dell'interprete con le varie componenti senza scendere in dettagli tecnico-implementativi, che restano nascosti "dentro" i vari "slave" Manager.
|