Article de reference

Bytecode

Le bytecode (également appelé code portable ou p-code ) est un ensemble d'instructions conçu pour une exécution efficace par un interpréteur de logiciels . Contrairement au code...

Le bytecode (également appelé code portable ou p-code ) est un ensemble d'instructions conçu pour une exécution efficace par un interpréteur de logiciels . Contrairement au code source lisible par l'homme , le bytecode est constitué de codes numériques compacts, de constantes et de références (généralement des adresses numériques) qui encodent le résultat de l'analyse syntaxique et sémantique effectuée par le compilateur sur des éléments tels que le type, la portée et le niveau d'imbrication des objets du programme.

Le terme « bytecode » provient des jeux d'instructions qui utilisent des codes d'opération (opcodes) d'un octet suivis de paramètres optionnels. Les représentations intermédiaires telles que le bytecode peuvent être générées par les implémentations de langages de programmation pour faciliter l'interprétation , ou utilisées pour réduire la dépendance au matériel et au système d'exploitation en permettant l'exécution d'un même code sur différentes plateformes , c'est-à-dire différents appareils. Le bytecode peut souvent être exécuté directement sur une machine virtuelle (une machine à code p , c'est-à-dire un interpréteur), ou être compilé en code machine pour de meilleures performances.

Étant donné que les instructions en bytecode sont traitées par logiciel, elles peuvent être d'une complexité arbitraire, mais sont néanmoins souvent similaires aux instructions matérielles traditionnelles : les machines à pile virtuelle sont les plus courantes, mais des machines à registres virtuels ont également été conçues. Différentes parties peuvent souvent être stockées dans des fichiers séparés, semblables à des modules objets , mais chargées dynamiquement lors de l'exécution.

Exécution

Un programme en bytecode peut être exécuté en analysant et en exécutant directement ses instructions, une à une. Ce type d' interpréteur de bytecode est très portable. Certains systèmes, appelés traducteurs dynamiques ou compilateurs à la volée (JIT), traduisent le bytecode en code machine à la demande, lors de l'exécution . Cela rend la machine virtuelle spécifique au matériel, mais ne compromet pas la portabilité du bytecode. Par exemple, le code Java et Smalltalk est généralement stocké au format bytecode, puis compilé à la volée (JIT) pour être traduit en code machine avant l'exécution. Cela introduit un délai avant l'exécution du programme, le temps que le bytecode soit compilé en code machine natif, mais améliore considérablement la vitesse d'exécution par rapport à l'interprétation directe du code source, généralement d'un facteur 10 environ.

Grâce à ses performances supérieures, de nombreuses implémentations de langages exécutent aujourd'hui un programme en deux phases : la compilation du code source en bytecode, puis le passage de ce bytecode à la machine virtuelle. Il existe des machines virtuelles de ce type, basées sur le bytecode, pour Raku , Python , PHP , Tcl , et Forth ( cependant , Forth est rarement compilé de cette manière et sa machine virtuelle est plus générique). Les implémentations de Perl et Ruby 1.8 fonctionnent quant à elles en parcourant une représentation arborescente de la syntaxe abstraite, dérivée du code source.

Plus récemment, les auteurs de V8 et de Dart ont remis en question l'idée qu'un bytecode intermédiaire soit nécessaire pour une implémentation de machine virtuelle rapide et efficace. Ces deux implémentations de langage effectuent actuellement une compilation JIT directe du code source vers le code machine sans intermédiaire de bytecode.

Exemples

( désassemblage ' ( lambda ( x ) ( print x ))) ; désassemblage pour (LAMBDA (X)) ; 2436F6DF : 850500000F22 TEST EAX, [#x220F0000] ; point d'entrée sans analyse d'arguments ; E5 : 8BD6 MOV EDX, ESI ; E7 : 8B05A8F63624 MOV EAX, [#x2436F6A8] ; #<objet FDEFINITION pour PRINT> ; ED : B904000000 MOV ECX, 4 ; F2 : FF7504 PUSH DWORD PTR [EBP+4] ; F5 : FF6005 JMP DWORD PTR [EAX+5] ; F8 : CC0A BREAK 10 ; gestion des erreurs ; FA : 02 BYTE #X02 ; FB : 18 octets #X18 ; erreur de comptage d'arguments invalide ; FC : 4F octets #X4F ; ECX
Le code compilé peut être analysé et examiné à l'aide d'un outil intégré de débogage du bytecode de bas niveau. Cet outil peut être initialisé depuis l'interpréteur de commandes, par exemple :
>>> import dis # "dis" - Désassembleur de bytecode Python en mnémoniques. >>> dis . dis ( 'print("Hello, World!")' )  1 0 LOAD_NAME 0 (print)  2 LOAD_CONST 0 ('Hello, World!')  4 CALL_FUNCTION 1  6 RETURN_VALUE