Nel precedente articolo abbiamo introdotto la modalità Thumb, soluzione adottata da ARM con la versione 4 della sua architettura per venir incontro alle necessità di maggior compattezza del codice, tipico del settore embedded.
Col passare del tempo e complice il dilagare di dispositivi portatili che sono diventati sempre più degli oggetti factotum (in particolare con la possibilità di far girare quelli che prima erano dei “giochini”, poi divenuti sempre più complessi) si è affacciata la necessità di eseguire applicazioni Java.
Impegnata in prima linea coi dispositivi mobile (se sono stati venduti più di 10 miliardi di microprocessori di questa famiglia è anche grazie all’esplosione di questo settore), ARM s’è trovata, quindi, di fronte al problema di come realizzare delle JVM (Java Virtual Machine) che girassero in maniera più efficiente sulle sue CPU, e ha tirato fuori dal cilindro Jazelle…
Avendo già sperimentato con successo la possibilità di eseguire opcode di ISA diverse da quella nativa (con Thumb, appunto), ha pensato bene di introdurre un’altra modalità di esecuzione che prendesse a modello l’ISA “virtuale” delle JVM, che eseguono codice Java sotto forma di bytecode.
Jazelle arriva nel 2000 con la versione 5 dell’architettura ARM, ma non viene automaticamente inclusa in tutte le CPU v5: si tratta di ben (!) 12mila transistor (ricordiamo che il solo core, quindi senza estensioni e cache varie, si aggira sui 35mila transistor) che possono anche non interessare i partner, per cui l’estensione è e rimane opzionale (a differenza di Thumb, il cui supporto è divenuto poi obbligatorio per tutti i microprocessori di questa famiglia).
L’ISA eseguita dalla JVM è, però, estremamente diversa dall’architettura ARM, da Thumb, e in generale da qualunque altra ISA general purpose già sviluppata. Non sarebbe, pertanto, pensabile che ARM si fosse imbarcata nell’opera di eseguirla completamente in hardware.
La strada percorsa è, infatti, ben diversa. Si tratta di mettere a disposizione un ambiente di esecuzione che faciliti l’esecuzione dei bytecode Java. Non a caso nel titolo dell’articolo parlavo di “accelerazione”, perché è proprio questo ciò che è stato deciso di realizzare dalla casa madre.
In questa modalità il funzionamento del processore cambia radicalmente sia nell’esecuzione delle istruzioni che nell’uso dei registri, i quali subiscono una specializzazione:
- da R0 a R3 vengono utilizzati per conservare i 4 elementi in cima allo stack Java (le JVM sono delle virtual machine di tipo “stack“)
- R4 memorizza il puntatore a this (cioè all’oggetto corrente su cui sta lavorando)
- R5 punta all’handler per la gestione delle istruzioni non eseguite direttamente / nativamente
- R6 rappresenta lo stack utilizzato dalla JVM (per memorizzare risultati intermedi e valori di ritorno dalle chiamate a funzione)
- R7 contiene l’indirizzo base delle variabili globali
- R8 punta alle costanti utilizzate dal codice in esecuzione
- da R9 a R11 sono a disposizione della virtual machine
- R12 è liberamente utilizzabile
- R13, come per la modalità Thumb, conserva il puntatore allo stack (non Java: è lo stack proprio dell’applicazione in esecuzione; in questo caso la JVM)
- R14, come R12, ma viene usato anche per contenere l’indirizzo di ritorno da una chiamata a funzione (similmente alle modalità ARM e Thumb: è il registro di “Link“)
- R15, infine, punta al bytecode da eseguire (è il PC, in sostanza)
Per capire meglio il funzionamento di Jazelle, si rende necessaria una spiegazione di massima sul workflow che porta all’esecuzione di bytecode (senza però entrare nel dettaglio del funzionamento di un virtual machine, che esula dallo scopo dell’articolo).
R15, come abbiamo visto, rappresenta il Program Counter della JVM, per cui viene utilizzato per leggere il bytecode da eseguire. In realtà l’ARM preleva una word, cioè 4 byte alla volta, e di questi provvede a scartare quelli inutili (quelli che, eventualmente, precedono il byte che interessa eseguire) e mantenere internamente tutti gli altri (quindi, oltre al byte da eseguire, anche gli eventuali successivi).
Operando in questo modo esegue una sorta di caching che riduce fino a 4 volte il numero di accessi alla memoria per il fetch delle istruzioni e dei loro dati. Questo perché l’ISA delle JVM prevede degli opcode a lunghezza variabile, dove il primo byte rappresenta il “codice identificativo” del bytecode da eseguire, a cui possono seguire altri byte utili all’istruzione.
Una volta prelevato il bytecode e gli eventuali dati che gli servono, Jazelle ha due possibilità: eseguirlo direttamente, oppure richiamare l’handler puntato da R5 a cui demandarne l’interpretazione e la successiva esecuzione.
Jazelle, infatti, non è in grado di eseguire in hardware tutte le quasi 240 istruzioni dell’ISA della JVM, ma soltanto 140 circa di esse vengono lette ed eseguite immediatamente. Le quasi 100 rimanenti richiedono la solita emulazione software prevista da una normale JVM (non dotata di JIT).
Lasciare quasi 100 istruzioni su 240 non emulate potrebbe far decadere considerevolmente le prestazioni, ma in realtà si tratta di bytecode raramente utilizzati. ARM stima, infatti, che meno del 5% del tempo d’esecuzione venga impiegato per farle girare, mentre quasi tutto il tempo la JVM esegue le 140 che sono, pertanto, le più comuni e sulle quali ha giustamente concentrato i suoi sforzi.
Un approccio ibrido, dunque, ma che si rivela azzeccato per svariati motivi:
- richiede una quantità relativamente piccola di transistor per l’implementazione (altre interamente in hardware sono anche di un ordine di grandezza più costose, in questi termini)
- il consumo viene ridotto considerevolmente
- le prestazioni sono molto più elevate rispetto a un interprete interamente software
- non si occupa spazio in più (a differenza delle JVM con JIT, che sono anche particolarmente esose in quanto devono memorizzare i blocchi di codice transcodificati)
Come al solito ARM si è dimostrata particolarmente attenta alle esigenze dei partner e del mercato, aggiungendo una preziosa freccia al suo arco che, anch’essa, ha contribuito sicuramente alle diffusione di quest’architettura facendola preferire ad altre.
Anche se c’è da dire che successivamente è tornata sui suoi passi, e le ultime incarnazioni della sua architettura non usano più Jazelle, ma s’è inventata una nuova soluzione (ThumbEE). Questa, però, è un’altra storia…