• Aucun résultat trouvé

Ce chapitre a présenté un aperçu de Bugloo, un débogueur pour tout langage compilé vers la JVM. Ce débogueur peut être contrôlé à la ligne de commande ou s’utiliser dans l’environnement de programmation Emacs. Il utilise une bibliothèque graphique afin de permettre l’inspection des objets structurés de manière efficace.

Les fonctionnalités du débogueur sont toutes exportées dans une interface de program- mation écrite en langage Scheme. Cette interface a un double usage : les utilisateurs s’en servent pour contrôler le débogueur à la ligne de commande et pour le personnaliser ; les implanteurs s’en servent pour construire des modules d’extension afin de supporter le débogage de leur langage.

Bugloo est conçu pour déboguer efficacement les langages nécessitant une compila- tion complexe. Les programmes peuvent disposer de plusieurs strates d’informations de débogage. De plus, l’inspection des données repose sur des mécanismes génériques spécia- lisables : les implanteurs peuvent fixer le comportement de la recherche des variables. Ils

3

voirhttp ://www.go-mono.com.

3.8. CONCLUSION peuvent aussi construire une représentation virtuelle des objets structurés de leurs langages et personnaliser leur affichage.

Chapitre 4

Filtrage de la pile d’exécution

L

e chapitre précédent a présenté une vue d’ensemble de Bugloo, notamment

les mécanismes dont il dispose pour masquer l’apparition de structures et de variables synthétiques dûes à la compilation des langages de haut niveau. Ce chapitre décrit le deuxième type de traitement mis en œuvre pour masquer les détails de compilation de ces langages. Ces mécanismes permettent tout d’abord de construire une vue virtuelle de la pile d’exécution durant l’inspection, afin de masquer les fonctions produites par le compilateur ou bien encore de visualiser dans une seule pile différentes représentations de code (typiquement du code natif et du code-octet). Ces mé- canismes permettent aussi d’effectuer une exécution pas-à-pas contrôlée, afin de ne jamais s’arrêter dans une fonction synthétique produite par le compilateur. La suite du chapitre présente les notations qui permettent de décrire le contenu de la pile d’exécution. Puis, sont décrits les mécanismes de construction de vue virtuelle et d’exécution contrôlée. Le chapitre se termine par une comparaison avec les travaux similaires dont le but est de masquer les détails de compilation qui apparaissent dans la pile d’exécution.

4.1 Le problème des blocs d’activation synthétiques

Comme évoqué dans le chapitre1, la compilation de certaines constructions des langages

de haut niveau (par exemple les fermetures) vers une plateforme d’exécution généraliste comme la JVM est une tâche complexe. Les transformations que subit un programme source durant sa compilation peuvent handicaper son débogage. Une des causes de cette difficulté de débogage est la présence dans la pile d’exécution de fonctions « privées » absentes du

code source du programme. La figure4.1illustre les principaux problèmes de débogage que

cela peut entraîner.

Le programme Java de la figure 4.1(b) donne une vision simplifiée du résultat de la

compilation du programme Bigloo de la figure 4.1(a). Ce programme contient un nom

d’identificateur encodé, ce qui n’est pas gênant lorsque le débogueur dispose de mécanismes

de visualisation adaptés (cf. chapitre 3). En revanche, la présence de fonctions synthétiques

entraîne deux problèmes majeurs. Tout d’abord, l’inspection de la pile de ce programme laisse apparaître ces artefacts de compilation, ce qui interfère avec l’image mentale que l’utilisateur a de l’exécution de son programme. De plus, ces artefacts perturbent fortement l’exécution pas-à-pas. Par exemple, un saut effectué pour sortir de la fonction hello amènera dans la fonction synthétique funcall1.

CHAPITRE 4. FILTRAGE DE LA PILE D’EXÉCUTION 1 (module test 2 (main go!)) 3 4 (define (hello s) 5 (print "hello " s)) 6

7 (define (go! args) 8 (let ((f hello)) 9 (f "world")))

(a) programme original

1 public class test extends proc {

2 procedure ptr_hello;

3 procedure ptr_BgL_goz12z12;

4

5 publicObjet funcall1(proc p, Object arg) {

6 switch (p.id) {

7 case 1: return hello(arg); 8 case 2: return BgL_goz12z12(arg);

9 default: returnbbool.faux;

10 }

11 }

12

13 publicObject hello(Object s) {

14 System.out.println("hello"+s);

15 }

16

17 publicObject BgL_goz12z12(Object args) { 18 procedure f=ptr_hello;

19 return f.funcall1(args);

20 }

21

22 public static void main(String[] argv) {

23 ptr_hello=new test(1);

24 ptr_BgL_goz12z12=new test(2);

25 BgL_goz12z12(runtime.wrap_args(argv));

26 }

27 }

(b) programme compilé

Fig. 4.1: Exemple de pollution apparente après la compilation d’un programme

4.1.1 Nature des blocs d’activations synthétiques

La pollution de la pile d’exécution peut survenir lorsque des abstractions de niveau « lan- gage » sont implantées dans une bibliothèque d’exécution. Par exemple, la bibliothèque de programmation GNOME [War04] fournit un système d’objet portable avec typage dyna- mique pour les programmes écrits en C pur. Les fonctionnalités comme la création d’objet ou la conversion de type dynamique (casts) sont implantées dans des fonctions qui appa- raissent dans la pile d’exécution, ce qui n’est pas désirable pour les débogueurs.

Certaines abstractions des langages de haut niveau sont implantées en produisant des fonctions synthétiques intermédiaires. Par exemple, les appels récursifs terminaux peuvent

être émulés avec des techniques dites de trampoline [Bak95,Cli98,SO01] qui utilisent une

fonction de contrôle pour appeler des fonctions utilisateur. Quand une fonction veut faire un appel terminal, elle retourne la fonction à appeler à la fonction de contrôle, qui n’a plus qu’à faire un appel de fonction standard. Ce type d’approche est extrêmement embêtant pour les débogueurs car l’information utile dans la pile peut se retrouver noyée dans un ensemble d’appels de fonctions synthétiques.

Parfois, la sémantique du langage source diffère tellement de celle de la plateforme d’exécution qu’une compilation directe est impossible. Dans ce cas, la compilation produit du code s’appuyant sur un interprète ad-hoc qui gère sa propre pile à l’exécution. C’est le cas par exemple de Jython [Hug97], qui embarque son propre interprète dans la JVM. Dans ce cas, les débogueurs standards ne sont plus capables d’instrumenter le programme et deviennent donc complètement inutiles.

4.2. DÉTECTION DE BLOC D’ACTIVATION