• Aucun résultat trouvé

2.8 Techniques d’implémentation utilisées dans les machines virtuelles

2.8.5 Hachage parfait

Le hachage parfait ( [Ducournau, 2008] pour son utilisation pour le test de sous- typage) est une technique d’implémentation des mécanismes objets s’appuyant sur une table de hachage. Cette table de hachage sera parfaite, c’est-à-dire qu’il n’y aura jamais de collisions.

Définition 14. Hachage parfait [Ducournau and Morandat, 2011] Pour I un ensemble non vide d’entiers. hash : N×N → N est une fonction telle que hash(x, y) < y et

hash(x, y) ≤ x pour tous x, y ∈ N . Le paramètre de hachage parfait de I est le plus petit H ∈ N telle que la fonction h qui pour x fait correspondre h(x) = hash(x, H) est injective sur I.

C’est à dire que pour tout x, y ∈ I, h(x) = h(y) implique x = y. Cette définition est étendue aux ensembles vides en considérant que H = 1 quand I = ∅.

Définition 15. Hachage parfait de classe [Ducournau and Morandat, 2011] Chaque classe se voit attribuer un identifiant unique lors de sa construction. Ce que l’on cherche à hacher est l’ensemble des identifiants des superclasses de la classe courante. Cet ensemble est forcément immutable puisqu’on ne changera jamais les superclasses d’une classe.

Soit (X, °) une hiérarchie de classe possédant des identifiants de classes injectifs id :

X ⇒ N . Le hachage parfait s’applique pour chaque classe c dans X en considérant l’ensemble Ic = {idd|c ° D} qui est immutable (les super-classes d’une classe sont connues et ne changeront jamais). Le paramètre Hc résultant est la taille de la table de hachage (représentée par un tableau) de la classe c. Et pour chaque superclasse d, la table contient idd à la position hc(idd). Toutes les autres positions j contiennent un entier quelconque l tel que hc(l) Ó= j.

hash(x, y) ≤ x est une contrainte qui n’est pas strictement nécessaire, mais elle a été vérifiée pour les fonctions de hachage testées dans [Ducournau and Morandat, 2011]. Ceci implique que hc(0) = 0 pour tout c. Dans les hiérarchies de classes avec une racine 0 est un identifiant convenable pour la racine et c’est aussi une valeur pour les entrées vides de la table aux positions j > 0. Pour les hiérarchies de classes sans racine, n’importe quel entier non-nul peut représenter une entrée vide à la position 0 de la table. Mais cet entier ne doit pas être utilisé pour numéroter une classe.

La fonction ET binaire (& dans la syntaxe C) est choisie comme fonction de hachage car elle représente le meilleur compromis entre plusieurs autres fonctions testées. Le

40 CHAPITRE 2. LANGAGES À OBJET ET MACHINES VIRTUELLES masque de hachage est ensuite stocké dans les classes et sera utilisé pour comme fonction de hachage en plus de l’identifiant de la classe. La taille de la table de hachage (masque+ 1) est déduite depuis le masque de hachage. Les classes sont donc numérotées dans l’ordre de leur chargement. La table de hachage parfaite est remplie par les identifiants des super-classes. Le hachage parfait garantit ensuite qu’il n’y aura pas de collisions dans la table de hachage. Ceci signifie que l’accès est réellement en temps constant.

Après ces différentes étapes, une implémentation basée sur le hachage parfait est réalisée de la manière suivante :

1. Récupération de l’identifiant de la classe testée (la cible)

2. Récupération du masque de hachage de la source du test (le type dynamique de l’objet)

3. L’opération masque&id renvoie une position

4. Le test consiste à tester si l’identifiant prévu est situé à la position renvoyée dans la table de hachage

L’espace occupé par les tables reste faible : il est linéaire dans la taille de la relation de spécialisation, cette condition ayant été vérifiée empiriquement. Le hachage parfait remplit les cinq exigences pour le test de sous-typage énoncées dans [Ducournau, 2008]. Cette technique a l’avantage d’être utilisable pour implémenter tous les mécanismes objets : l’appel de méthode, l’accès aux attributs et le test de sous-typage. Elle est néanmoins plus lente que des implémentations en héritage simple, il faut donc essayer d’optimiser pour ne l’utiliser que quand elle est strictement nécessaire.

Le test de sous-typage est implémenté en testant si on trouve son identifiant dans la classe qui est source du test. L’appel de méthode nécessite de récupérer ensuite la position du bloc de classe qui a introduit la méthode appelée. Cette position est récupérée dans la table de hachage également. l’accès aux attributs est implémenté en récupérant la position du bloc de la classe qui a introduit l’attribut en question. Cette position est également stockée dans la table de hachage parfaite.

La figure 2.8 illustre l’utilisation du hachage parfait. Des pointeurs vers les itable des classes sont présents dans la table de hachage. Une itable est le début du bloc d’une classe dans la table de méthodes. La figure 2.9 présente la séquence de code abstraite pour un appel de méthode avec le hachage parfait.

La technique du hachage parfait impose une structure des tables de méthodes pour être utilisée. La table de méthode est partagée en deux parties : la partie négative contient la table de hachage parfaite et la partie positive contient les méthodes.

La table de hachage parfaite contient à la position appropriée des pointeurs vers la partie positive de la table de méthodes. La partie positive est partagée en plusieurs blocs, chaque bloc est constitué de la manière suivante :

— L’identifiant de la classe est à la première position

— Le ∆ (noté d(A) sur le schéma) sert à implémenter l’accès aux attributs en héritage multiple. Le δ correspond au décalage du bloc d’attributs introduits par la classe dans la table d’attributs des objets de la classe.

2.8. TECHNIQUES D’IMPLÉMENTATION UTILISÉES DANS LES MACHINES VIRTUELLES41

Figure 2.8 – Schéma d’implémentation des méthodes avec le hachage parfait

B x = new D() x.bar()

load [object + #tableOffset], table load [table + #hashingOffset], h and #AId, h, hv

mul hv, #2*fieldLen, hv sub table, hv, htable

itable = offset du bloc concerné load [htable +#htOffset], itable load [itable +#barOffset], method call method

42 CHAPITRE 2. LANGAGES À OBJET ET MACHINES VIRTUELLES — Le code des différentes méthodes de la classe

Il est possible d’utiliser cette technique pour implémenter les interfaces et le test de sous-typage dans une machine virtuelle Java comme montré dans [Pagès, 2013].