Machine virtuelle Althread
Etat de la machine virtuelle
L'état de la machine virtuelle est représenté par
- La valeur des variables globales d'un côté
- L'état des canaux de communications (les messages en transit)
- Une structure pour chaque processus en cours d'exécution. L'état d'un processus en exécution contient sa pile d'exécution, c'est-à-dire les variables locales des processus, et la valeur du pointeur d'instruction, qui est l'index de l'instruction en cours d'exécution.
La pile d'execution d'un processus ne contient pas d'information de débuggage, elle contient uniquement les valeurs des variables locales et les valeurs intermédiaires des expressions sous forme d'un tableau de Literal
.
Les expressions utilisant des variables locales utilisent l'index de la variable dans la pile d'ex écution du processus. L'index d'une variable locale est déterminé lors de la compilation, ce qui permet un accès rapide durant l'exécution.
Pour simplifier, les variables globales sont stockés dans une HashMap (un dictionnaire) et leur valeur est directement accessible par leur nom.
Instructions
Les instructions de la machine virtuelles sont représentées par un enum InstructionType
. Chaque instruction contient des champs avec les informations nécessaires pour l'exécution de l'instruction:
Instruction vide, ne fait rien.
Évalue une expression et ajoute le résultat sur la pile. LocalExpressionNode
est la racine d'un arbre représentant l'expression.
Ajoute le literal donné sur la pile.
Retire unstack_len
valeurs de la pile.
Remplace le tuple situé au sommet de la pile par ses éléments. Un tuple contenant 3 éléments sera remplacé par 3 valeurs sur la pile.
Ajoute les valeurs des variables globales sur la pile. Le champs only_const
indique si les variables sont toutes des constantes (si c'est le cas, l'instruction peut être optimisée car elle n'est pas globale).
Assigne la valeur au sommet de la pile à la variable globale identifier
donnée, puis retire unstack_len
valeurs de la pile.
Assigne la valeur au sommet de la pile à la variable locale d'index index
donnée, puis retire unstack_len
valeurs de la pile.
Déclare une variable dans le scope courant initialisée avec la valeur au sommet de la pile, puis retire unstack_len
valeurs de la pile.
Démarre un nouveau thread exécutant le programme name
avec comme argument la valeur au sommet de la pile, puis retire unstack_len
valeurs de la pile. Finalement, ajoute le pid du thread sur la pile.
Appelle la fonction name
avec les arguments locaux aux indexes donnés, puis retire unstack_len
valeurs de la pile. Si variable_idx
est donné, la fonction est une méthode de l'objet à l'index donné.
Finalement, ajoute le résultat de la fonction sur la pile, si elle retourne une valeur.
Saute à l'instruction jump_false
si la valeur au sommet de la pile est fausse, puis retire unstack_len
valeurs de la pile. La valeur du saut est relative à l'instruction courante: si jump_false
vaut -2
, alors le saut se fait à l'instruction courante moins 2.
Saute à l'instruction jump
. La valeur du saut est relative à l'instruction courante.
Saute à l'instruction jump
en retirant unstack_len
valeurs de la pile. Si stop_atomic
est vrai, arrête l'exécution atomique.
Regarde si un message est disponible dans le canal channel_name
. Si c'est le cas ajoute le message et la valeur true
sur la pile, sinon ajoute false
sur la pile.
Retire le message du canal channel_name
(sans l'ajouter sur la pile).
Démarre une attente sur une conditions utilisant les dépendances données. Si start_atomic
est vrai, démarre une section atomique. Les dépendances sont des variables globales ou des canaux dont la valeur est utilisée dans la condition. Cette instruction ne modifie pas l'état de la machine virtuelle, elle est utilisée uniquement pour indiqué l'entrée dans une zone d'attente. De plus un processus en attente attendra obligatoirement sur cette instruction. Cependant, ce n'est pas cette instruction seule qui permet de déterminé si le processus est en attente. L'attente est déterminée par la l'exécution de l'instruction Wait
qui doit renvoyer le processus en attente sur l'instruction WaitStart
.
Si le sommet de la pile est false
, saute à l'instruction jump
(donné en position relativement à l'instruction suivante), sinon passe à l'instruction suivante.
Dans tous les cas unstack_len
valeurs sont dépilées.
Envoie la valeur au sommet de la pile dans le canal channel_name
, puis retire unstack_len
valeurs de la pile.
Connecte les canaux sender_channel
et receiver_channel
entre les processus sender_pid
et receiver_pid
. Si sender_pid
ou receiver_pid
est None
, alors le processus courant est utilisé.
Lors de la connexion, si le processus envoyeur à déjà effectué un Send
sur le canal, le message est directement déposé dans le channel du processus receveur.
Démarre une section atomique. Les sections atomiques sont des zones de code où les processus ne peuvent pas être interrompus. Cela permet d'éviter les problèmes de concurrence. Une section atomique est terminée par une instruction AtomicEnd
. Elle ne doit pas contenir d'instructions d'attente, sauf si c'est la première instruction.
Termine une section atomique.
Termine le processus courant.
Termine tous les processus.
L'enum InstructionType
est défini dans le fichier /vm/src/instruction.rs.