• Aucun résultat trouvé

6.2 Conception d'un pré-interpréteur

6.2.1 Architecture générale

6.2.1.1 Surcharge de la pile d'accès à la mémoire non-adressable

La gure 6.2a, page 106 rappelle la constitution de la pile d'accès à la mémoire non- adressable par une exécution en place dans un tampon. La gure 6.2b représente celle de l'utilisation classique d'un cache. La gure 6.2c décrit quand à elle l'architecture que nous proposons. Elle garde l'utilisation d'un cache mais place entre lui et l'interpréteur une nou- velle couche de gestion de l'exécution qui ordonnance la pré-interprétation, l'interprétation concrète diérée et la gestion anticipée des défauts de cache.

Dans ces schémas, nous séparons l'interpréteur concret principal qui consomme essen- tiellement des bytecodes, et les handlers qui consomment à la fois du code (les opérandes) et des méta-données. Comme nous l'avons vu ces deux types de données ne sont pas utilisés de la même façon. Nous avons vu notamment que les méta-données modiaient la notion de séquentialité d'un bloc de base en lisant des données dans une page de cache potentiellement diérente. Cet aspect est donc un point important de la recherche de plages séquentielles

Interpréteur Handlers FTL

Pilote Flash série

(a) Pile d'accès à la Flash série par le tampon de la FTL. Interpréteur Handlers Cache logiciel Espace de cache FTL Pilote Flash série (b) Pile d'accès à la Flash série par un cache. Interpréteur Handlers Pré-Interpréteur Analyseur Pré-chargement Cache logiciel Espace de cache FTL Pilote Flash série

(c) Pile d'accès à la Flash série par un cache

avec préparateurs de code.

Figure 6.2: Piles d'accès à la Flash série.

qui ne rompent pas la condition n◦3 de l'encadré page 103, i.e. la modication intempestive du cache.

6.2.1.2 Principe de fonctionnement

La boucle principale qui est à l'origine de l'interprétation classique est remplacée pour une boucle étendue regroupant un pré-interpréteur et un interpréteur concret. Un cycle complet est représenté dans le diagramme de séquence 6.3, page 107. Dans ce diagramme apparaissent toujours les phases classiques de l'interprétation d'un bytecode, à savoir la récupération de l'instruction, son décodage, son exécution, et le repositionnement du poin- teur d'instructions. Il n'y a pas de changement dans l'ordre de ces phases car elles ne peuvent pas être interverties. Cependant, le changement d'approche globale que nous pro- posons conduit à réaliser des actions diérentes au sein de chacune de ces phases.

Récupération L'étape de récupération s'attache à transformer l'adresse virtuelle d'une instruction de tête vers son adresse physique en RAM. Si cette instruction est absente du cache, alors elle est récupérée depuis la mémoire non-adressable par le canal normal du cache. À cette étape, l'instruction récupérée est toujours et uniquement une instruction de tête, propriété garantie par un cycle complet, et notamment par l'analyse du code.

La refonte de cette étape est la résolution de la condition n◦1 de l'encadré page 103, à savoir, la dénition d'un couple adresse-virtuelle/adresse-physique marquant le début d'une plage d'adresses accessibles directement par l'interpréteur concret.

Décodages multiples Le remodelage de cette étape de l'interprétation classique est le c÷ur de notre nouvelle approche. C'est en eet à cet instant que se déroule l'analyse de code dont le but est la délimitation d'une plage d'adresses en RAM,  exécutable  par l'interpréteur concret sans accès au cache. Le travail d'analyse a pour but de mettre en ÷uvre de la condition n◦2 de l'encadré page 103, à savoir la détermination des limites de la plage d'adresses physiques.

Indirectement, mais eectivement, cette analyse participe à la récupération et au pré- décodage de tous les bytecodes que contiendra cette plage, mais aussi certaines méta-données si elles sont analysables hors-contexte d'exécution. En eet, à n d'avancer dans le code du bloc de base pour en trouver la limite, chaque bytecode est décodé pour estimer s'il s'agit d'un rupteur de ot, pour calculer l'adresse du bytecode suivant, mais aussi évaluer certaines opérandes accédant à des méta-données. Ainsi, de façon précoce, le bloc de base complet

Phase Interpréteurconcret Interpréteur AnalyseurPré- Cache Récupèration Multipes Décodages Multipes Exécutions Incrémentation en bloc récupérer (@virt) Hit ou Miss instrTête instrTête, curPage

analyser( instrTête, curPage )

TANT QUE cond != faux alimenter plage

FIN TANT QUE pré-chargement

plage

TANT QUE plage != vide exécuter()

FIN TANT QUE naliser pré-chargement brancher() traitement opérande Hit ou Miss méta-donnée recaler_contexte nouvelle@virt

Figure 6.3: Schéma de pré-interprétation de code avec décodages et exécutions groupés de bytecodes

sera entièrement pre-décodé en n de cycle d'une analyse. Enn et surtout, on peut dire alors que chaque bytecode a été  articiellement  récupéré, sans qu'il n'y ait eu besoin d'accéder au cache par son interface logicielle.

Exécutions multiples À cette étape, la plage d'adresses décodée est fournie à l'interpré- teur concret pour exécution. Son pointeur d'instruction est positionné en début de plage physique et commence l'interprétation concrète de bytecodes déjà décodés. La plage entière est alors exécutée dans les même conditions de performance que si l'application était stockée dans une mémoire adressable.

Incrémentation par bloc Le calcul de la plage d'adresse principale (i.e. celle du bloc de base, hors méta-données) xe un IP physique de départ et un IP physique de n. Lors de l'exécution de l'interpréteur concret, IP courant est contrôlé après chaque exécution de routines d'interprétation jusqu'à ce que celui-ci soit égal à celui de n. Il est alors retraduit en adresse virtuelle pour que puisse recommencer un nouveau cycle de pré-interprétation. Description du nouvel ordonnancement Les conséquences et eets des diérences d'approche entre l'interpréteur classique et un pré-interpréteur sont illustrées par les gures 6.4 et 6.5. R1 D1 E1 I1 R2 D2 E2 I2 R3 D3 E3 I3 R4 D4 E4 I4 C4 Hit ou Miss C3 Hit ou Miss C2 Hit ou Miss C1 Hit ou Miss

R: Récupération, D : Décodage, E : Exécution, I : Incrémentation, C : Accès au cache Figure 6.4: Interprétation classique avec accès systématiques au cache

R1 D1 D2 D3 D4 E1 E2 E3 E4 I1 `a 4

Pré-chargement C1 Hit ou Miss

Figure 6.5: Cycle de pré-interprétation

Fondamentalement, la pré-interprétation ne réduit pas le temps d'exécution d'un dé- codage ou d'une exécution de handler. Là n'est pas le but. Cependant, le fait de décoder précocement les instructions permet de réduire l'impact du coût de l'analyse de code sur chaque cycle d'interprétation.

Le point important est sans conteste le nombre d'accès au cache évités. C'est sur cet aspect et sur le gain qu'il représente que repose la performance nale de la pré-interprétation par rapport à l'approche classique.

Le second gain possible est celui-ci des pré-chargements de blocs de données. Grouper des décodages, permet de les décorréler de leur exécution immmédiate. L'analyse permet de voir plus loin que le bytecode courant, ce qui permet une recherche anticipée d'autres bytecodes susceptibles de déclencher des défauts de cache. Lancer un pré-chargement permet

ainsi d'exécuter une série de bytecodes pendant que la Flash non-adressable prépare la page de données à charger en cache.