El código de bytes (también llamado código portátil o código p ) es una forma de conjunto de instrucciones diseñado para una ejecución eficiente por parte de un intérprete de software . A diferencia del código fuente legible por humanos [1] , los códigos de bytes son códigos numéricos compactos, constantes y referencias (normalmente direcciones numéricas) que codifican el resultado del análisis del compilador y la realización del análisis semántico de cosas como el tipo, el alcance y las profundidades de anidamiento de los objetos del programa.
Dado que las instrucciones de código de bytes son procesadas por software, pueden ser arbitrariamente complejas, pero no obstante suelen ser similares a las instrucciones de hardware tradicionales: las máquinas de pila virtual son las más comunes, pero también se han construido máquinas de registro virtual. [2] [3] A menudo, las diferentes partes se pueden almacenar en archivos separados, similares a los módulos de objetos , pero se cargan dinámicamente durante la ejecución.
Ejecución
Un programa de bytecode puede ejecutarse analizando y ejecutando directamente las instrucciones, una a la vez. Este tipo de intérprete de bytecode es muy portátil. Algunos sistemas, llamados traductores dinámicos o compiladores Just-In-Time (JIT), traducen el bytecode a código de máquina según sea necesario en tiempo de ejecución . Esto hace que la máquina virtual sea específica del hardware, pero no pierde la portabilidad del bytecode. Por ejemplo, el código Java y Smalltalk se almacena normalmente en formato de bytecode, que normalmente se compila JIT para traducir el bytecode a código de máquina antes de la ejecución. Esto introduce un retraso antes de que se ejecute un programa, cuando el bytecode se compila a código de máquina nativo, pero mejora considerablemente la velocidad de ejecución en comparación con la interpretación directa del código fuente, normalmente en alrededor de un orden de magnitud (10x). [4]
Debido a su ventaja de rendimiento, hoy en día muchas implementaciones de lenguaje ejecutan un programa en dos fases, primero compilando el código fuente en bytecode y luego pasando el bytecode a la máquina virtual. Hay máquinas virtuales basadas en bytecode de este tipo para Java , Raku , Python , PHP , [a] Tcl , mawk y Forth (sin embargo, Forth rara vez se compila a través de bytecodes de esta manera, y su máquina virtual es más genérica en cambio). La implementación de Perl y Ruby 1.8 en cambio funciona recorriendo una representación de árbol de sintaxis abstracta derivada del código fuente.
Más recientemente, los autores de V8 [1] y Dart [7] han cuestionado la noción de que se necesita un bytecode intermedio para una implementación de VM rápida y eficiente. Ambas implementaciones de lenguaje actualmente realizan compilación JIT directa desde el código fuente al código de máquina sin un bytecode intermedio. [8]
Ejemplos
ActionScript se ejecuta en la máquina virtual ActionScript (AVM), que forma parte de Flash Player y AIR . El código ActionScript normalmente se transforma en formato de código de bytes mediante un compilador . Algunos ejemplos de compiladores incluyen uno integrado en Adobe Flash Professional y otro integrado en Adobe Flash Builder y disponible en Adobe Flex SDK .
La implementación CLISP de Common Lisp solía compilar solo en código de bytes durante muchos años; sin embargo, ahora también admite la compilación en código nativo con la ayuda de GNU Lightning.
EM, la máquina virtual Amsterdam Compiler Kit utilizada como lenguaje de compilación intermedio y como lenguaje de bytecode moderno
Emacs es un editor de texto cuyas funciones están implementadas en su mayoría por Emacs Lisp , su dialecto integrado de Lisp . Estas funciones se compilan en código de bytes. Esta arquitectura permite a los usuarios personalizar el editor con un lenguaje de alto nivel que, después de compilarlo en código de bytes, ofrece un rendimiento razonable.
Common Lisp ofrece una disassemblefunción [10] que imprime en la salida estándar el código subyacente de una función especificada. El resultado depende de la implementación y puede o no resolverse en código de bytes. Su inspección se puede utilizar para fines de depuración y optimización. [11] Steel Bank Common Lisp , por ejemplo, produce:
( desensamblar ' ( lambda ( x ) ( imprimir x ))) ; desensamblado para (LAMBDA (X)) ; 2436F6DF: 850500000F22 TEST EAX, [#x220F0000] ; punto de entrada de análisis sin argumentos ; E5: 8BD6 MOV EDX, ESI ; E7: 8B05A8F63624 MOV EAX, [#x2436F6A8] ; #<objeto FDEFINITION para PRINT> ; ED: B904000000 MOV ECX, 4 ; F2: FF7504 PUSH DWORD PTR [EBP+4] ; F5: FF6005 JMP DWORD PTR [EAX+5] ; F8: CC0A BREAK 10 ; trampa de error ; FA: 02 BYTE #X02 ; FB: 18 BYTE #X18; ERROR DE CONTEO DE ARGUMENTOS INVÁLIDOS ; FC: 4F BYTE #X4F; ECX
La implementación de Erlang por parte de Ericsson utiliza códigos de bytes BEAM
LSL, un lenguaje de programación utilizado en mundos virtuales, se compila en código de bytes que se ejecuta en una máquina virtual. Second Life tiene la versión Mono original, Inworldz desarrolló la versión Phlox.
El lenguaje Lua utiliza una máquina virtual de código de bytes basada en registros
El entorno R para computación estadística ofrece un compilador de bytecode a través del paquete compiler, ahora estándar con la versión R 2.13.0. Es posible compilar esta versión de R de modo que los paquetes base y recomendados lo aprovechen. [18]
Los scripts de Python se compilan durante la ejecución en el lenguaje de bytecode de Python, y los archivos compilados (.pyc) se almacenan en caché dentro de la carpeta del script.
El código compilado se puede analizar e investigar mediante una herramienta integrada para depurar el código de bytes de bajo nivel. La herramienta se puede inicializar desde el shell, por ejemplo:
>>> import dis # "dis" - Desensamblador de código de bytes de Python en mnemónicos. >>> dis . dis ( 'print("¡Hola, mundo!")' ) 1 0 LOAD_NAME 0 (print) 2 LOAD_CONST 0 ('¡Hola, mundo!') 4 CALL_FUNCTION 1 6 RETURN_VALUE
Esquema 48: implementación de Scheme utilizando un intérprete de bytecode
Códigos de bytes de muchas implementaciones del lenguaje Smalltalk
^ PHP tiene compilación justo a tiempo en PHP 8, [5] [6] y antes, aunque no estaba activada en la versión predeterminada, tenía opciones como HHVM . Para versiones anteriores de PHP: Aunque los códigos de operación de PHP se generan cada vez que se inicia el programa, y siempre se interpretan y no se compilan justo a tiempo .
Referencias
^ ab "Generación dinámica de código de máquina". Google Inc. Archivado desde el original el 5 de marzo de 2017. Consultado el 21 de febrero de 2023 .{{cite web}}: CS1 maint: bot: original URL status unknown (link)
^ "La implementación de Lua 5.0".(NB. Esto implica una máquina virtual basada en registros).
^ "Dalvik VM". Archivado desde el original el 18 de mayo de 2013. Consultado el 29 de octubre de 2012 .(NB. Esta VM se basa en registros).
^ "Código de bytes frente a código de máquina". www.allaboutcomputing.net . Consultado el 23 de octubre de 2017 .
^ O'Phinney, Matthew Weier. "Explorando el nuevo compilador JIT de PHP". Zend de Perforce . Consultado el 19 de febrero de 2021 .
^ "PHP 8: El JIT - stitcher.io". stitcher.io . Consultado el 19 de febrero de 2021 .
^ Loitsch, Florian. "¿Por qué no una máquina virtual de código byte?". Google . Archivado desde el original el 12 de mayo de 2013.
^ "Mito de JavaScript: JavaScript necesita un código de bytes estándar". 2ality.com .
^ G., Adam Y. (11 de julio de 2022). "Berkeley Pascal". GitHub . Consultado el 8 de enero de 2022 .
^ "CLHS: Función DESMONTAR". www.lispworks.com .
^ "Ajuste del rendimiento y consejos". lispcookbook.github.io .
^ "La implementación del lenguaje de programación Icon" (PDF) . Archivado desde el original (PDF) el 2016-03-05 . Consultado el 2011-09-09 .
^ "La implementación de Icon y Unicon: un compendio" (PDF) . Archivado (PDF) del original el 2022-10-09.
^ Paul, Matthias R. (30 de diciembre de 2001). «Estructura interna de KEYBOARD.SYS». Grupo de noticias : comp.os.msdos.programmer. Archivado desde el original el 9 de septiembre de 2017. Consultado el 17 de septiembre de 2016. […] De hecho, el formato es básicamente el mismo en MS-DOS 3.3 - 8.0, PC DOS 3.3 - 2000, incluidas las versiones en ruso, lituano, chino y japonés, así como en Windows NT, 2000 y XP […]. Hay pequeñas diferencias e incompatibilidades, pero el formato general no ha cambiado con el paso de los años. […] Algunas de las entradas de datos contienen tablas normales […] Sin embargo, la mayoría de las entradas contienen código ejecutable interpretado por algún tipo de intérprete de código p en * tiempo de ejecución *, incluidas las ramas condicionales y similares. Es por esto que el controlador KEYB ocupa una cantidad de memoria tan grande en comparación con los controladores de teclado controlados por teclado, que pueden ejecutarse en 3-4 Kb y obtener el mismo nivel de función, excepto el intérprete. […]
^ Mendelson, Edward (2001-07-20). "Cómo mostrar el euro en MS-DOS y Windows DOS". Mostrar el símbolo del euro en MS-DOS de pantalla completa (incluido Windows 95 o Windows 98 en modo DOS de pantalla completa). Archivado desde el original el 2016-09-17 . Consultado el 2016-09-17 . […] Matthias [R.] Paul […] advierte que la versión DOS de IBM PC del controlador del teclado utiliza algunos procedimientos internos que no son reconocidos por el controlador de Microsoft , por lo que, si es posible, debe utilizar las versiones de IBM de KEYB.COM y KEYBOARD.SYS en lugar de mezclar las versiones de Microsoft e IBM […](NB. Lo que se entiende por "procedimientos" aquí son algunos códigos de bytes adicionales en el archivo IBM KEYBOARD.SYS que no son compatibles con la versión de Microsoft del controlador KEYB).
^ "Patente de los Estados Unidos 6.973.644". Archivado desde el original el 5 de marzo de 2017. Consultado el 21 de mayo de 2009 .
^ Especificaciones de código P de Microsoft C. p. 13. Multiplan no se compiló en código de máquina , sino en un tipo de código de bytes que se ejecutaba mediante un intérprete , para que Multiplan fuera portátil en el hardware muy variado de la época. Este código de bytes distinguía entre el formato de punto flotante específico de la máquina para realizar los cálculos y un formato externo (estándar), que era decimal codificado en binario (BCD). Las instrucciones PACK y UNPACK convertían entre los dos.
^ "Instalación y administración de R". cran.r-project.org .
^ "El motor de bytecode de SQLite". Archivado desde el original el 14 de abril de 2017. Consultado el 29 de agosto de 2016 .