Notes de la séance 3 de TransProg M2
====================================

Javix : Une idéalisation d’un fragment de la JVM

Visite guidée:

Session de démo dans la console Scala:

import trac._
import IntOp._
import javix.AST._
val codejavix = List(Push(6),Push(7),IOp(Add),IPrint,Return)
val progjavix = Program("Test",codejavix,100,100)
javix.PP.pp(progjavix)
Trac.writeFile("Test.j",javix.PP.pp(progjavix))
javix.Interp.eval(progjavix)
javix.Interp.eval(progjavix,true)

Fopix2Javix : Compilation directe de Fopix vers Javix

Première tâche pour le projet : écrire une traduction directe de Fopix vers Javix.
A débuter dès aujourd’hui (TP3), au moins pour les parties faciles.

Validateur JVM

Il est normal que le code Javix produit par Fopix2Javix soit
fréquemment refusé par le validateur de la JVM, vu que notre usage
de la pile ne sera pas forcément prévisible à l’avance.
Du coup pour l’instant: java -noverify FooBar

Arrêt

L’exécution de votre code Javix doit terminer par un Return.
Il n’y a donc pas de réponse finale, par contre vos exemples
contiendront sans doute des affichages (IPrint et SPrint).

Convention d’appel de fonction:

Appels recursifs terminaux (tail calls)

Si le code de la fonction f se termine par un appel à une autre
fonction g (qui peut être f de nouveau en cas de récursion),
pas besoin de sauvegarder des variables, ni de placer une adresse
de retour sur la pile : on peut s’arranger pour recycler l’adresse
de retour de l’appel en cours à f lors du lancement de g !
C’est l’optimisation des appels terminaux. Attention, le tout premier
appel de fonction ne peut être optimisé (pas encore d’adresse de
retour). Pour l’instant, ne pas chercher à changer le code que l’on
compile pour le rendre récursif terminal.

Boxing

La pile peut contenir:

Pour satisfaire le “typage” de la JVM, nous utiliserons souvent
des nombres “boxés”, c’est-à-dire mis dans une zone allouée dans le
tas, et accessible uniquement via un pointeur. Cela correspond
à la différence en Java entre int (le type primitif) et Integer
(l’objet contenant un entier). Ici nous utiliserons des tableaux
de taille 1 pour “boxer” nos entier, les pseudo-instructions
Box et Unbox permettant ce “boxage” et l’opération inverse.

Les opérations arithmétiques de la JVM et les comparaisons
fonctionnent seulement sur des entiers non-boxés.

Normalement les variables de la JVM peuvent également contenir
des valeurs boxées ou non-boxées (AStore et ALoad versus IStore
et ILoad). Mais le validateur de la JVM peut protester si une
variable particulière change de type de contenu. Il est donc fortement
recommandé de ne mettre que des valeur boxées dans les variables.

Pour les tableaux, seules les opérations “boxées” sont fournies:
ANewarray, AAStore, AALoad

Evidemment, ces opérations d’allocation et d’accès mémoire ne sont
pas gratuites, on pourra chercher à minimiser le nombre de Box
et Unbox utilisées, par exemple via des optimisations comme la
suppression des groupes d’instructions Box;Unbox ou Unbox;Box.

Nombres de variables, taille de pile

Pour les premiers essais, vous pouvez indiquer à Javix un nombre de
variables et une taille de pile farfelus (p.ex. 100 et 10000).

Vous pouvez dès maintenant déterminer le nombre de variables utilisées
dans le code que vous venez de compile, et indiquer ce nombre exact
dans l’entête de Javix. C’est un simple “max” sur les ALoad et
AStore que vous avez engendrés.

Par contre la taille de pile nécessaire à l’exécution d’un code Javix
peut actuellement être non-borné. Vous pouvez éventuellement mener ce
calcul dans le cas d’un code non-récursif, ou dans le cas d’un code
100% récursif terminal (avec l’optimisation correspondante).