Prev   Top   Next 

La struttura dello Stack

Il funzionamento della Macchina Astratta è basato sul suo Stack, poiché esso è coinvolto nell'interpretazione di ogni bytecode del programma; ciò perchè è tramite lo Stack Manager e quindi lo Stack, che l'interprete ha accesso a parte delle informazioni sullo stato corrente della macchina.

I singoli elementi dello Stack, che vengono creati dallo Stack Manager e quindi inseriti e rimossi dallo Stack, sono detti Stack Frame. In figura è schematizzata la struttura dello Stack, di cui si evidenzia uno Stack Frame.

Struttura dello Stack

I vari Stack Frame vengono creati al momento dell'invocazione di un metodo, e restano sullo Stack finché l'esecuzione dei relativi bytecode non è terminata, in seguito ad un'istruzione Return. In ogni istante la porzione di Stack al di sopra di un dato Frame mantiene le informazioni associate alle invocazioni di metodi generate, direttamente o indirettamente, dal metodo relativo al Frame in questione. Quando questi metodi avranno terminato la loro esecuzione e restituito i loro risultati, sarà necessario ripristinare lo stato dell'interprete al momento della prima invocazione.
A tale scopo in ogni Stack Frame è presente un'area, detta Environment d'esecuzione o semplicemente Environment, che memorizza cinque puntatori: Sender, PC, OPTOP, VARS e Class Structure.

Il puntatore chiamato Sender fa riferimento all'Environment dello Stack Frame del metodo che ha invocato l'esecuzione del metodo corrente. Tale riferimento sarà necessario per consentire allo Stack Manager di ritrovare le informazioni contenute nell'Environment del Frame precedente.

Si osservi che delle tre aree che costituiscono la struttura dello Stack Frame, due hanno lunghezza variabile, diversa da metodo a metodo, e precisamente la prima o area delle variabili locali e l'ultima o stack degli operandi.
Pertanto il campo Sender individua il Frame precedente non tramite la sua base ( dalla quale non saprebbe risalire alle altre parti ), ma puntando all'Environment, dove si trovano anche i puntatori alle altre aree.
Tali puntatori non sono altro che il campo VARS, che fa riferimento all'area delle variabili ( e quindi alla base del Frame ), e OPTOP che punta al Top dello stack degli operandi. Questi campi, insieme con il campo PC, costituiscono dei valori di backup che vengono caricati negli omonimi registri dell'interprete.

L'area delle variabili contiene il riferimento all'oggetto ( this ) su cui si sta eseguendo il metodo ( nel caso di metodi istanza ), nonché gli argomenti passati al metodo corrente e le sue variabili locali. Il metodo corrente può manipolare il valore di queste variabili solo tramite lo stack degli operandi, caricandovi il loro valore o prelevando dal top i nuovi risultati. Tale meccanismo è usato per tutte le operazioni su numeri e oggetti; è per questo motivo che sono presenti, nell'Instruction Set, due categorie di istruzioni correlate allo stack degli operandi: le PUSH, che consentono di caricare i valori da varie parti della macchina sul top dello stack, e di converso le POP, che memorizzano il valore che si trova sul top dello stack in varie aree di memoria.

Ma lo stack degli operandi ha anche un'altro uso, che spiega un po' il motivo per cui ogni Stack Frame ha l'organizzazione mostrata in figura: esso viene utilizzato per passare gli argomenti ai metodi.
Subito prima dell'invocazione di un metodo, il chiamante si preoccupa di caricare sullo stack l'oggetto sul quale agirà il metodo ( nel caso di metodi istanza ) e i suoi argomenti. Quindi lo Stack Manager provvede a creare un nuovo Frame per il dato metodo, e lo alloca facendo sí che si sovrapponga parzialmente su quello precedente, di modo che la porzione dello stack degli operandi che contiene gli argomenti coincida con l'inizio dell'area della variabile del nuovo Frame.

Ma come fa lo Stack Manager a sapere di quanto deve "scendere" nello stack degli operandi per prendere tutti gli argomenti del nuovo metodo? Questa informazione viene ricavata dagli operandi del bytecode, che costituiscono un indice a 16 bits in una tabella ( la Run-Time Costant Pool ) all'interno della struttura puntata dal campo Class Structure.
I dettagli di ciò verranno trattati assieme alla Method Area e al Class Manager: in breve, la entry ottenuta tramite questo indice contiene un descrittore del metodo che si sta invocando, che ci fornisce informazioni sul numero e tipo di argomenti e sul fatto che si tratti o meno di un metodo istanza.

 Prev   Top   Next