Maison  >  Article  >  développement back-end  >  Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

王林
王林avant
2023-05-26 12:13:201577parcourir

Implémentation du flux de contrôle

Flux de contrôle Cette partie du code implique principalement les instructions de bytecode suivantes. Toutes les instructions de bytecode suivantes auront un paramètre :

  • JUMP_FORWARD. la position de l'instruction, puis passez au résultat correspondant pour continuer l'exécution.

  • Si l'élément supérieur de la pile est vrai, l'instruction pour modifier la position d'exécution du bytecode par la valeur du paramètre reçu est "POP_JUMP_IF_TRUE". Retirez l'élément supérieur de la pile.

  • POP_JUMP_IF_FALSE, cette instruction est la même que POP_JUMP_IF_TRUE, la seule différence est de déterminer si l'élément supérieur de la pile est égal à vrai.

  • JUMP_IF_TRUE_OR_POP, si l'élément supérieur de la pile est égal à true, la position d'exécution du bytecode est définie sur la valeur correspondant au paramètre, et il n'est pas nécessaire de faire apparaître l'élément supérieur de la pile. Si l'élément supérieur de la pile est faux, l'élément doit être sauté.

  • JUMP_IF_FALSE_OR_POP, identique à JUMP_IF_TRUE_OR_POP sauf que l'élément supérieur de la pile doit être égal à false.

  • JUMP_ABSOLUTE, définit directement la position d'exécution du bytecode sur la valeur du paramètre.

En général, ces instructions de saut permettent à l'interpréteur Python de modifier le flux d'exécution en fonction de conditions spécifiques lors de l'exécution du bytecode et d'implémenter des structures de langage de base telles que des boucles et des instructions conditionnelles.

Nous utilisons maintenant un exemple pour comprendre en profondeur le processus d'exécution des différentes instructions ci-dessus.

La sortie du programme ci-dessus au-dessus de Risee 的 est présentée ci-dessous :

6 0 LOAD_CONST 1 (1)

2 Store_fast 0 (A)
8 4 LOAD_FAST 0 (A)
6 load_const 1 (1)
8 compare_op 4 ( & gt;) o 10 pop_jump_if_false 22

9 12 load_global 0 (print)
14 load_const 2 ('a & gt; 1')
16 call_function 1
18 POP_TOP
20 jump_Forward 26 (à 4 8)
1 0 & gt; & gt; 22 load_fast 0 (a)
24 load_const 1 (1)
26 compare_op 0 (& lt;)
28 POP_JUMP_IF_FALSE 40
11 30 Load_global 0 (Imprimer)
32 Load_Const 3 ('A & LT; 1 ; POP_TOP
& G t; & gt; 48 load_const 0 (Aucun)
                                                                                                                                                  Simulons maintenant le processus d'exécution du bytecode ci-dessus. Nous utilisons le compteur pour représenter la position d'exécution du bytecode actuel :

Avant que l'exécution du bytecode ne commence, l'espace de la pile et. Le statut du compteur est le suivant :



Maintenant, exécutez le premier bytecode LOAD_CONST. Après exécution, compteur = 2. Comme ce bytecode occupe un octet et que la pile de paramètres est un octet, la position du bytecode exécuté la prochaine fois est dans les trois inférieures de la position du bytecode, la position correspondante. l'indice est 2, donc compteur = 2.

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

Maintenant, exécutez le deuxième bytecode STORE_FAST, laissez un point sur 1, le même opcode et le même opérande STORE_FAST occupent chacun un octet, donc il n'y a aucune donnée dans l'espace de la pile après l'exécution de ce bytecode, compteur = 4.

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

Ensuite, LOAD_FAST charge l'objet pointé par a, qui vaut 1, dans la pile à ce moment, counter = 6. LOAD_CONST charge la constante 1 dans l'espace de pile à ce moment, counter = 8. Après avoir exécuté ces deux instructions, les modifications dans l'espace de pile sont comme indiqué dans la figure ci-dessous :

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

L'instruction suivante est COMPARE_OP. Cette instruction a un paramètre représentant le symbole de comparaison. Ici, elle compare un > 1, et le résultat de la comparaison sera poussé dans la pile, le résultat de la comparaison est faux, car COMPARE_OP affichera d'abord les deux entrées de l'espace de pile. Par conséquent, après avoir exécuté cette instruction, les valeurs de l'espace de pile et. counter sont les suivants :

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

L'instruction suivante est POP_JUMP_IF_FALSE , selon la signification du bytecode précédent, ce bytecode fera apparaître le faux en haut de la pile, sautera et programmera directement la valeur du compteur à la valeur du paramètre. Ici son paramètre est 22, donc compteur = 22, Après avoir exécuté cette instruction, le résultat est le suivant :

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

Comme il est maintenant passé à 22, la prochaine instruction à exécuter est LOAD_FAST, qui charge la variable a dans l'espace de pile, et LOAD_CONST charge la constante 1 dans l'espace de pile. Après avoir exécuté ces deux exécutions, les changements sont les suivants :

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

Exécutez à nouveau POP_JUMP_IF_FALSE, cette fois le résultat est également faux, alors continuez. pour exécuter POP_JUMP_IF_FALSE, cette fois le paramètre est 40, définissez directement la valeur du compteur sur 40 .

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

Ensuite, LOAD_GLOBAL charge un compteur de fonction d'impression de variable globale et devient 42, LOAD_CONST charge la chaîne "a == 1" dans l'espace de pile, compteur = 44, et l'état est le suivant :

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

CALL_FUNCTION Le code de section a un paramètre, indiquant le nombre de paramètres pour appeler la fonction, ici c'est 1, car la fonction d'impression n'a qu'un seul paramètre, puis génère la chaîne "a== 1", mais cela doit être noté ici. que la fonction d'impression retournera None. Par conséquent, après avoir exécuté CALL_FUNCTION, l'état est le suivant :

Comment implémenter le flux de contrôle du bytecode de la machine virtuelle Python

À ce stade, la fonction ci-dessus a presque été exécutée. Les prochains bytecodes sont très simples et ne seront pas décrits à nouveau. .

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer