• Aucun résultat trouvé

Détection de motifs de blocs d’activation dans la pile

la pile. Pour pouvoir décrire la configuration de la pile, il faut maintenant un moyen de détecter si un groupe de blocs d’activation consécutifs se trouve sur la pile. Cela nécessite l’introduction d’un nouveau langage de motif nommé Omega. Ce langage permet de décrire des successions de blocs d’activation dans la pile. Dans ce nouveau type de détection de motif, analogue aux expressions régulières classiques, la chaîne de caractères est remplacée par la pile d’exécution et les caractères par les blocs d’activation.

4.3.1 Le langage de motif Omega

Omega est composé de caractères qui sont en fait des filtres de bloc et d’un ensemble de méta-caractères permettant la construction et la composition de motifs de bloc d’activa- tion. À la différence des expressions régulières classiques, les mots du langage Omega sont représentés sous une forme « pré-digérée » qui reflète la structure logique arborescente d’un motif. Les mots du langage sont construits comme indiqué ci-dessous :

ω ∈ Omega =                                ǫ mot vide;

φ ∈ Filter filtre de bloc;

ω1.ω2 concaténation de deux mots de Omega;

(6= φ1· · · φn) complément de l’ensemble de filtres de bloc φi;

(| ω1· · · ωn) choix de l’un des mots ωi;

(∗ ω) répétition du mot ω (étoile de Kleene [Kle56]);

(? ω) apparition optionnelle de ω, équivalent à (| ω ǫ);

(+ ω) au moins une répétition de ω, équivalent à ω.(∗ ω)

La détection de motif de blocs s’effectue grâce à la fonction match_stack, dont l’algo-

rithme est présenté dans la figure4.3. Cette fonction de détection prend en paramètre une

séquence de blocs d’activation qui sont consécutifs dans la pile d’exécution du débogué, un motif de pile ω ∈ Omega et une mémoire initialement vide servant à la capture d’attri- buts de blocs d’activation. En retour, elle renvoie un triplet dont le premier élément est un booléen indiquant s’il existe un entier i ≤ n tel que les i premiers blocs d’activation de la séquence soient reconnus par ω. En cas de détection, le second argument représente les i premiers blocs et le troisième argument, les blocs d’activation restant dans la liste.

La détection d’une suite consécutive de blocs d’activation est un algorithme itératif si- milaire à la détection de motif dans une chaîne de caractères. À chaque étape, les arguments de la fonction match_stack ont la forme suivante :

match_stack(f1. . .↑fi. . .fn, ω.Ω, M )

Dans la figure, un pointeur dénoté par une flèche verticale apparaît dans le premier argument pour indiquer la progression de la détection. À gauche du pointeur se trouvent les blocs

4.3. DÉTECTION DE MOTIFS DE BLOCS D’ACTIVATION DANS LA PILE

match_stack: [Frame] × Omega × Memory−→Bool × [Frame] × [Frame]

fonction match_stack(f1. . .↑fi. . .fn, ω.Ω, M ) :

si ω.Ω ≡ ∅ alors

match_stack← htrue, f1. . .fi, fi+1. . .fni

sinonsi ω ≡ φ et match(fi, φ, M ) = htrue, M′i alors

match_stack← match_stack(f1. . .fi↑fi+1. . .fn, Ω, M′)

sinonsi ω ≡ (6= φ1. . . φm) et ∀j ∈ [1, m] | match(fi, φj, M ) = hfalse, M′i alors

match_stack← match_stack(f1. . .fi↑fi+1. . .fn, Ω, M′)

sinonsi ω ≡ (| ω1. . . ωm) et ∃j ∈ [1, m] | match_stack(↑fi. . .fn, ωj.Ω, M ) = htrue, F, Gi alors

match_stack← htrue, f1. . .fi−1.F, Gi

sinonsi ω ≡ (∗ω′) et match_stack(↑fi. . .fn, ω.(∗ω).Ω, M ) = htrue, F, Gi alors

match_stack← htrue, f1. . .fi−1.F, Gi

sinonsi ω ≡ (∗ω′) et match_stack(↑f

i. . .fn, ω′.(∗ω′).Ω, M ) = hfalse, ∅, ∅i alors

match_stack← match_stack(f1. . .↑fi. . .fn, Ω, M )

sinon

match_stack← hfalse, ∅, ∅i

finsi

Fig. 4.3: L’algorithme de détection de motif de blocs.

qui ont déjà été reconnus par le motif de pile initial Ω0 ; à droite du pointeur se trouvent

les blocs restant dans le flot d’entrée. Le second argument ω.Ω représente ce qu’il reste du

motif initial Ω0 après avoir détecté i − 1 blocs dans le flot d’entrée.

Lorsque la détection commence, le pointeur se trouve à l’extrémité gauche du flot de blocs d’activation. Si un groupe de blocs se trouvant directement à droite du pointeur correspond au motif ω, le pointeur avance d’un bloc d’activation dans la séquence et le motif à détecter est réduit à Ω. Ainsi, une séquence de blocs d’activation est reconnue par un motif de bloc si ce dernier peut être réduit à ∅ par une suite d’itérations de l’algorithme. En corollaire, on peut noter que les blocs du flot ne doivent pas forcément être consommés en totalité pour que la correspondance ait lieu.

4.3.2 Exemples de syntaxe concrète

La syntaxe concrète des motifs de blocs se base sur l’utilisation de listes Lisp. Les caractères du langage Omega sont des filtres de bloc. La concaténation de motifs est n-aire et elle est représentée par une liste Lisp dont les éléments sont les motifs. Les autres méta- opérations sont représentées par un doublet dont le premier élément est le méta-caractère et le second une liste d’opérandes (des filtres de bloc ou des motifs de blocs comme vu précédemment). Pour illustrer cette syntaxe, voici un motif de blocs permettant de détecter les séquences de blocs d’activation de la forme |foo, bar, . . . | ou |foo, gee, hux, . . . | et qui rejette les séquence comme |hux, bar, foo, . . . | :

[("foo" any any any any) (| ("bar" any any any any)

("gee" any any any any))]

Dans un motif de pile, on peut utiliser les références aux valeurs capturées pour per- mettre une comparaison structurelle entre plusieurs blocs d’activation. La détection de motif se sert de la fonction match pour tester la correspondance entre un filtre du motif et un bloc

CHAPITRE 4. FILTRAGE DE LA PILE D’EXÉCUTION

d’activation dans la pile. En sortie de fonction, l’état de la mémoire est conservé pour être ensuite passé en paramètre au prochain appel à match. De cette manière, on peut détecter des motifs de manière « contextuelle ». Par exemple, on peut écrire un motif qui détecte dans la pile une fonction de nom et d’argument arbitraire, immédiatement suivie d’une

fonction du même nom préfixé par un tiret et ayant la même configuration d’argument2 :

[((? "foo") (? any) any any any) ("_\\1" (\ 2) any any any)]

4.3.3 Les motifs de pile comme condition d’arrêt

Le langage Omega offre un moyen de décrire le contenu de la pile d’exécution et per- met aux implanteurs de langage de définir des motifs de blocs d’activation à masquer ou à transformer afin de pouvoir présenter à l’utilisateur une pile expurgée des artefacts de compilation. Mais ce langage se révèle aussi très intéressant pour obtenir des points d’arrêt conditionnels activés lorsque la pile d’exécution se trouve dans une configuration particu- lière. Par exemple, il devient possible de suspendre l’exécution dans la fonction foo d’un programme prog1 seulement si foo a été appelée depuis la fonction bar :

(bp add prog1 foo :stack ((foo any any any any) (bar any any any any)))

Dans Bugloo, on utilise l’attribut :stack pour activer un point d’arrêt si le motif associé correspond au sommet de la pile d’exécution.

4.4 Construction d’une vue virtuelle de la pile d’exécution