Pour en savoir plus
Les techniques de compilation vers des machines abstraites ont été
utilisées par les premières implantations de SmallTalk, puis ont été
reprises pour les langages fonctionnels LISP ou ML. L'argument, réel,
de perte d'efficacité due aux machines abstraites a rejeté un temps
dans l'ombre cette technique. Cependant, aujourd'hui, la langage JAVA
en fait un argument de vente. Les machines abstraites possèdent
plusieurs avantages. Le premier est de faciliter le portage d'un
compilateur vers différentes architectures. En effet la partie du
compilateur à réécrire pour un portage est bien cernée (l'interprète
de la machine abstraite et une partie de la bibliothèque
d'exécution). D'autre part elles permettent la portabilité du code
produit. Il est possible de compiler une application sur une
architecture système-machine et de l'exécuter sur une autre. Enfin
elles permettent de simplifier l'écriture du compilateur en ajoutant
des instructions spécifiques pour le type de langage à compiler. Dans
le cas des langages fonctionnels, les machines abstraites permettent
de créer facilement des fermetures (couple environnement, code) en
ajoutant à la machine abstraite la notion d'environnement d'exécution.
Pour pallier la perte d'efficacité due à l'utilisation d'un
interprète de code-octet, on peut procéder à une expansion
des instructions de la machine abstraite vers les instructions de la
machine réelle au moment de leur chargement. On trouve ce type
d'expansion dans les implantations de Le Lisp (llm3) et de JAVA
(JIT). Néanmoins ces performances ne peuvent égaler celles
d'un compilateur natif ou vers C.
Une difficulté de la compilation des langages fonctionnels
provient des fermetures. Ces dernières contiennent en effet le code à
exécuter ainsi que l'environnement d'exécution de ce code (voir page
??).
Les choix d'implantation des environnements et de l'accès aux valeurs
qu'ils contiennent influencent fortement l'efficacité du code
produit. Une optimisation importante de la gestion des environnements
consiste à obtenir un accès aux valeurs en temps constant : les
variables sont vues comme des indices dans un tableau contenant leur
valeur. Cela nécessite un prétraitement des expressions
fonctionnelles. On en trouve un premier exemple dans la Functional Abstract Machine de L. Cardelli. La Zinc utilise également
cette technique. Une autre optimisation cruciale est d'éviter de
construire des fermetures inutiles. Bien qu'en ML toute fonction
puisse être vue comme une fonction à un argument, il est indispensable
de ne pas créer de fermetures intermédiaires lors de l'application de
plusieurs arguments. Par exemple, quand on applique deux entiers
à la fonction add, il n'est pas utile de construire la
première fermeture correspondant à la fonction
add appliquée au premier argument. Il faut noter que la
création d'une fermeture nécessite l'allocation d'un certain espace
mémoire pour l'environnement donc en allouer trop déclenchera plus
souvent le récupérateur automatique de mémoire
(9). Or, la récupération automatique de mémoire est le
deuxième point sensible pour les performances.
Enfin la propriété d'auto-amorçage (bootstrap) permet
d'écrire la plus grande partie du compilateur dans le langage qu'il
doit compiler. Pour cela, comme la poule et l'oeuf, il est nécessaire
de définir la partie minimale du langage permettant ensuite de
l'augmenter. En fait cette propriété est difficilement appréciable
pour classifier les langages et leurs implantations. Disons que cela
sert pour montrer la capacité d'un langage à être langage
d'implantation pour un compilateur. Un compilateur est un
programme d'une bonne taille et l'auto-amorçage est un bon test de
la correction du compilateur qui permet d'évaluer ses performances.
Donnons comme référence le lien suivant :
Lien
http://caml.inria.fr/camlstone.txt
On y trouve les temps de compilation du langage Caml sur une
cinquantaine de machines. Ces temps sont pour des versions plus
anciennes qu'Objective CAML mais permettent de se faire une idée de
l'efficacité d'un couple machine-système pour Objective CAML.