web-dev-qa-db-fra.com

Pourquoi les VM doivent-elles être des "machines à empiler" ou des "machines à enregistrer", etc.?

(C'est une question extrêmement novice).

J'ai étudié un peu les machines virtuelles.

Il s'avère que beaucoup d'entre eux sont conçus de manière très similaire aux ordinateurs physiques ou théoriques.

J'ai lu que la JVM par exemple, est une "machine à pile". Ce que cela signifie (et corrigez-moi si je me trompe), c'est qu'il stocke toute sa "mémoire temporaire" sur une pile et effectue des opérations sur cette pile pour tous ses opcodes.

Par exemple, le code source 2 + 3 sera traduit en bytecode similaire à:

Push 2
Push 3
add

Ma question est la suivante:

Les JVM sont probablement écrites en C/C++ et autres. Si c'est le cas, pourquoi la JVM n'exécute-t-elle pas le code C suivant: 2 + 3 ..? Je veux dire, pourquoi a-t-il besoin d'une pile, ou dans les autres registres de VM - comme dans un ordinateur physique?

Le processeur physique sous-jacent s'occupe de tout cela. Pourquoi les rédacteurs VM exécutent-ils simplement le bytecode interprété avec des instructions "habituelles" dans le langage avec lequel est programmé VM?)

Pourquoi les machines virtuelles doivent-elles émuler le matériel, alors que le matériel réel le fait déjà pour nous?

Encore une fois, des questions très novices. Merci de votre aide

48
Aviv Cohn

Une machine, virtuelle ou non, a besoin d'un modèle de calcul qui décrit comment le calcul y est effectué. Par définition, dès qu'il calcule, il implémente un certain modèle de calcul. La question est alors: quel modèle choisir pour notre VM? Les machines physiques sont contraintes par ce qui peut être fait efficacement et efficacement dans le matériel. Mais, comme vous le constatez, les machines virtuelles n'ont pas de telles contraintes, elles sont définies dans des logiciels utilisant des langages de niveau arbitrairement élevé.

Il existe en fait des machines virtuelles de haut niveau comme vous le décrivez. Ils sont appelés langages de programmation. Le standard C, par exemple, consacre la majeure partie de ses pages à la définition d'un modèle pour la soi-disant "machine abstraite C" qui décrit comment les programmes C se comportent, et par extension (comme une règle) comment un compilateur C conforme (ou interprète) Devrait se comporter.

Bien sûr, nous n'appelons généralement pas cela une machine virtuelle. A VM signifie généralement quelque chose de niveau inférieur, plus proche du matériel, non destiné à être directement programmé, conçu pour être exécuté efficacement. Ce biais de sélection signifie que quelque chose qui accepte un composable de haut niveau le code (comme ce que vous décrivez) ne serait pas considéré comme un VM car exécute du code de haut niveau.

Mais pour aller droit au but, voici quelques raisons de faire un VM (comme dans quelque chose ciblé par un compilateur de bytecode) basé sur un registre ou similaire. Les machines à empiler et à enregistrer sont extrêmement simples . Il existe une séquence d'instructions, un état et une sémantique pour chaque instruction (une fonction État -> État). Aucune réduction d'arbre complexe, aucune priorité d'opérateur. L'analyse, l'analyse et l'exécution sont très simples, car il s'agit d'un langage minimal (syntaxique le sucre est compilé) et conçu pour être lu par machine plutôt que lu par l'homme.

En revanche, analyser même les langages de type C les plus simples est assez difficile, et son exécution nécessite des analyses non locales comme la vérification et la propagation des types, la résolution des surcharges, le maintien d'une table de symboles, la résolution de la chaîne identificateurs, transformant le texte linéaire en un AST piloté par la priorité, et ainsi de suite. Il s'appuie sur des concepts qui sont naturels pour l'homme, mais doivent être minutieusement inversés par les machines.

Le bytecode JVM, par exemple, est émis par javac. Il n'a pratiquement jamais besoin d'être lu ou écrit par les humains, il est donc naturel de l'adapter à la consommation par les machines. Si vous l'avez optimisé pour les humains, la JVM lire à chaque démarrage le code, l'analyser, l'analyser, puis le convertir en une représentation intermédiaire ressemblant à un tel modèle de machine simplifié de toute façon . Autant découper l'homme du milieu.

51
user7043

Cette réponse se concentre sur la JVM, mais en fait, elle s'applique à n'importe quelle machine virtuelle.

Pourquoi les machines virtuelles doivent-elles émuler le matériel, alors que le matériel réel le fait déjà pour nous?

Ils ne le font pas, mais cela rend le VM beaucoup plus simple et portable: A VM qui émule le matériel peut utiliser le même modèle de calcul que n'importe quel processeur matériel).

La JVM en particulier a été construite avec la portabilité à l'esprit, en fait, elle a été conçue pour pouvoir même être implémentée dans le matériel (cela peut être difficile à croire aujourd'hui, mais le Origin of Java était dans le monde embarqué - spécifiquement, contrôleurs pour télévision interactive).

Si vous avez un objectif comme celui-ci, il est souhaitable que le VM fonctionne aussi près que possible d'une machine physique, car la traduction en code machine réel devient plus facile et donc plus rapide. Une fois que vous avez les opcodes de la VM, en théorie, tout ce que vous avez à faire est de traduire en opcodes du CPU sur lequel le programme fonctionne réellement. En pratique, ce n'est pas aussi simple que cela.

Je veux dire, pourquoi a-t-il besoin d'une pile, ou dans d'autres registres de VM - comme dans un ordinateur physique?

L'utilisation d'un modèle de machine virtuelle basé sur une pile présente l'avantage de pouvoir être facilement transféré à la fois sur des machines de registre et de pile, tandis que l'inverse n'est pas nécessairement vrai. Un VM basé sur un registre devrait faire des hypothèses sur le nombre de registres, la taille des registres, etc. Avec une machine à pile, aucune hypothèse de ce type n'est nécessaire.

Le processeur physique sous-jacent s'occupe de tout cela. Pourquoi les rédacteurs VM exécutent-ils simplement le bytecode interprété avec des instructions "habituelles" dans le langage avec lequel est programmé VM?)

Eh bien, c'est ce que font ces machines virtuelles, elles interprètent le bytecode. Même la JVM le fait, au moins avant que JIT (juste à temps) n'intervienne: elle interprète les codes d'octets et exécute les instructions dans le langage dans lequel la JVM a été écrite (généralement C ou C++, mais il y en a même une écrite en JavaScript, Doppio ). Notez, cependant, que même de telles instructions ont été traduites en code machine par un compilateur et ressemblent en fait à ce que le compilateur Java produit - à savoir, elles utilisent des registres et la pile pour effectuer leur travail. Notez que l'utilisation des langages "interprétés" vs "compilés" devient quelque peu floue à ce stade.

20
miraculixx

Pourquoi les machines virtuelles doivent-elles être des "machines à empiler" ou des "machines à enregistrer", etc.?

Ils ne. Si vous avez besoin d'une machine virtuelle, cela peut être n'importe quoi.

Les machines virtuelles existantes sont apparues comme des solutions aux situations comme: ne idée vraiment géniale m'est venue à l'esprit, j'ai inventé un nouveau langage de programmation! Mais je dois générer du code. (Quelle tâche ennuyeuse!) Mais Je ne veux pas générer de code i8086 parce que c'est moche, et je ne veux pas générer de code 68k parce que tout le monde utilise Intel. Il y a aussi VAX, mais je n'ai pas de VAX, ni un ordinateur ni un livre VAX. Par conséquent Je vais générer du code pour un processeur qui n'existe pas physiquement et l'implémenter dans un logiciel. La spécification de cela VM fera un chapitre dans ma thèse. En théorie, il sera possible de compiler au code natif de n'importe quel processeur, mais ce ne sera pas moi.

D'un autre côté, la notation comme "2 + 3" ne sera probablement pas utilisée par les VM dans un avenir prévisible car elle implique de faire beaucoup de transformation avant que quelque chose puisse être exécuté.

11