Bytecode

El bytecode o código intermedio es un lenguaje intermedio más abstracto que el lenguaje máquina. Habitualmente, es tratado como un archivo binario que contiene instrucciones destinadas a ser ejecutadas por una máquina virtual, a diferencia de un módulo objeto tradicional producido por el compilador, cuyo contenido es código objeto o código máquina.

El código intermedio recibe su nombre porque usualmente el código de operación (opcode) tiene una longitud de un byte, si bien la longitud total de las instrucciones puede variar. Cada instrucción tiene un código de operación entre 0 y 255 seguido de parámetros tales como los registros o las direcciones de memoria. Esta sería la descripción de un caso típico, si bien la especificación del bytecode depende ampliamente del lenguaje.

Como código intermedio, se trata de una forma de salida utilizada por los implementadores de lenguajes para reducir la dependencia respecto del hardware específico y facilitar la interpretación o ejecución en distintos entornos. Menos frecuentemente se utiliza el bytecode como código intermedio en un compilador. Algunos sistemas, llamados traductores dinámicos o compiladores justo a tiempo, traducen el bytecode a código máquina inmediatamente antes o durante su ejecución para mejorar la velocidad de ejecución.

Los programas en bytecode suelen ser interpretados por un intérprete de bytecode (en general, llamado máquina virtual, dado que es análogo a un ordenador). Su ventaja es su portabilidad: el mismo código binario puede ser ejecutado en diferentes plataformas y arquitecturas. Es la misma ventaja que presentan los lenguajes interpretados. Sin embargo, como el bytecode es en general menos abstracto, más compacto y más orientado a la máquina que un programa pensado para su modificación por humanos, su rendimiento suele depender del diseño de la máquina virtual y de las técnicas de ejecución empleadas. A causa de esa mejora en el rendimiento, muchos lenguajes interpretados, de hecho, se compilan para convertirlos en bytecode y después son ejecutados por un intérprete de bytecode. Entre esos lenguajes se encuentran Perl, Gambas, PHP y Python. En el caso de Java se suele transmitir como bytecode a la máquina receptora, que puede utilizar un compilador just-in-time para compilar el bytecode en código máquina nativo antes o durante su ejecución.

Son asimismo interesantes los denominados códigos p, similares a los códigos intermedios pero cuyos códigos de operación pueden constar de más de un byte y pueden ser variables en tamaño, como los opcodes de muchas CPU. Estos códigos trabajan a muy alto nivel, incluyendo instrucciones del estilo de «imprime esta cadena» o «borra la pantalla». Por ejemplo, BASIC utiliza p-Code.

En noviembre de 2019, Mozilla, Fastly, Intel y Red Hat forman la Bytecode Alliance, una empresa que tiene por finalidad promover el uso del lenguaje WebAssembly en entornos Linux e integrando cualquier navegador como Safari, Chrome o Firefox.

Ejemplos

>>> 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

Referencias

  1. ↑ Wolf, Gunnar (9 de septiembre de 2015). Fundamentos de sistemas operativos. Lulu.com. ISBN 978-607-02-6544-0. Consultado el 5 de agosto de 2022.
  2. ↑ Pérez, Juan Carlos Moreno. Programación Orientada a Objetos. Grupo Editorial RA-MA. Consultado el 5 de agosto de 2022.
  3. ↑ Zapien, Rosa Hernández de Lapién (2005). Apex Computer Science Terminology for Interpreters. English-Spanish glossary.. Rosie Zapien. ISBN 978-0-9772521-4-5. Consultado el 5 de agosto de 2022.
  4. ↑ «Mozilla, Fastly, Intel y Red Hat forman la Bytecode Alliance.».