SpiderMonkey es un motor de código abierto de JavaScript y WebAssembly de la Fundación Mozilla . [4] El motor impulsa el navegador web Firefox y ha utilizado varias generaciones de compiladores just-in-time (JIT) de JavaScript , incluidos TraceMonkey, JägerMonkey, IonMonkey y el actual WarpMonkey.
Es el primer motor de JavaScript , escrito por Brendan Eich en Netscape Communications, y posteriormente lanzado como código abierto y actualmente mantenido por la Fundación Mozilla. Su diseño permite su integración en aplicaciones más allá de los navegadores web, con implementaciones que incluyen el sistema de base de datos MongoDB, Adobe Acrobat y el entorno de escritorio GNOME.
Eich "escribió JavaScript en diez días" en 1995, [5] habiendo sido "reclutado para Netscape con la promesa de 'hacer Scheme ' en el navegador". [6] (La idea de usar Scheme fue abandonada cuando "la gerencia de ingeniería [decidió] que el lenguaje debía 'parecerse a Java ' ".) [6] A fines de 1996, Eich, que necesitaba "pagar [la] deuda técnica sustancial " que le quedaba del primer año, "se quedó en casa durante dos semanas para reescribir Mocha como la base de código que se conocería como SpiderMonkey". [5] (Mocha era el nombre de trabajo original para el lenguaje). [6] [7] En 2011, Eich transfirió la administración del código SpiderMonkey a Dave Mandelin. [5]
SpiderMonkey implementa la especificación ECMA-262 ( ECMAScript ). La especificación ECMA-357 ( ECMAScript para XML (E4X)) se abandonó a principios de 2013. [10]
SpiderMonkey está escrito en C / C++ y contiene un intérprete , el compilador JIT WarpMonkey y un recolector de basura .
TraceMonkey [11] fue el primer compilador JIT escrito para el lenguaje JavaScript. Inicialmente presentado como una opción en una versión beta y presentado en el blog de Brendan Eich el 23 de agosto de 2008, [12] el compilador se convirtió en parte de la versión principal como parte de SpiderMonkey en Firefox 3.5 , proporcionando "mejoras de rendimiento que van entre 20 y 40 veces más rápido" que el intérprete de línea base en Firefox 3. [ 13]
En lugar de compilar funciones completas, TraceMonkey era un JIT de seguimiento que funcionaba registrando el flujo de control y los tipos de datos durante la ejecución del intérprete. Estos datos luego informaban la construcción de árboles de seguimiento , rutas altamente especializadas de código nativo .
Las mejoras de JägerMonkey acabaron por hacer que TraceMonkey quedara obsoleto, especialmente con el desarrollo del motor de inferencia de tipos SpiderMonkey . TraceMonkey no está presente en SpiderMonkey a partir de Firefox 11. [14]
JägerMonkey, internamente llamado MethodJIT, fue un compilador JIT de métodos completos diseñado para mejorar el rendimiento en casos en los que TraceMonkey no podía generar código nativo estable . [15] [16] Se lanzó por primera vez en Firefox 4 y eventualmente suplantó por completo a TraceMonkey. A su vez, ha sido reemplazado por IonMonkey.
JägerMonkey funcionaba de forma muy diferente a otros compiladores de su clase: mientras que los compiladores típicos funcionaban construyendo y optimizando un gráfico de flujo de control que representaba la función, JägerMonkey funcionaba iterando linealmente hacia adelante a través del bytecode de SpiderMonkey , la representación interna de la función. Aunque esto prohíbe las optimizaciones que requieren reordenamiento de instrucciones, la compilación de JägerMonkey tiene la ventaja de ser muy rápida, lo que es útil para JavaScript, ya que la recompilación debido al cambio de tipos de variables es frecuente.
Mozilla implementó una serie de optimizaciones críticas en JägerMonkey, las más importantes son los cachés en línea polimórficos y la inferencia de tipos . [17]
La diferencia entre las técnicas JIT de TraceMonkey y JägerMonkey y la necesidad de ambas se explicó en un artículo de hacks.mozilla.org. Chris Leary, uno de los desarrolladores de SpiderMonkey, proporcionó una explicación más detallada de los detalles técnicos en una publicación de blog archivada el 9 de diciembre de 2012 en archive.today . Puede encontrar más información técnica en los blogs de otros desarrolladores: dvander, dmandelin.
IonMonkey fue un compilador JIT de JavaScript de Mozilla, cuyo objetivo era permitir muchas optimizaciones nuevas que eran imposibles con la arquitectura JägerMonkey anterior. [18]
IonMonkey era un compilador más tradicional: traducía el bytecode de SpiderMonkey a un gráfico de flujo de control , utilizando la forma de asignación única estática (SSA) para la representación intermedia . Esta arquitectura permitió que se utilizaran optimizaciones conocidas de otros lenguajes de programación para JavaScript, incluida la especialización de tipos, la inserción de funciones en línea, la asignación de registros de escaneo lineal , la eliminación de código muerto y el movimiento de código invariante en bucles . [19]
El compilador puede emitir traducciones rápidas de código nativo de funciones de JavaScript en las plataformas ARM , x86 y x86-64 . Ha sido el motor predeterminado desde Firefox 18. [20]
OdinMonkey es el nombre del nuevo módulo de optimización de Mozilla para asm.js , un subconjunto de JavaScript fácilmente compilable. OdinMonkey en sí no es un compilador JIT, sino que utiliza el compilador JIT actual. Está incluido en Firefox desde la versión 22.
El JIT WarpMonkey reemplaza al antiguo motor IonMonkey de la versión 83. [21] Es capaz de incorporar en línea otros scripts y especializar el código en función de los datos y argumentos que se procesan. Traduce el código de bytes y los datos de caché en línea en una representación intermedia de nivel medio (Ion MIR). Este gráfico se transforma y optimiza antes de ser reducido a una representación intermedia de nivel bajo (Ion LIR). Esta LIR realiza la asignación de registros y luego genera código de máquina nativo en un proceso llamado Generación de código. Las optimizaciones aquí suponen que un script continúa viendo datos similares a los que se han visto antes. Los JIT de línea base son esenciales para el éxito aquí porque generan IC que coinciden con los datos observados. Si después de compilar un script con Warp, encuentra datos que no está preparado para manejar, realiza un rescate. El mecanismo de rescate reconstruye el marco de pila de la máquina nativa para que coincida con el diseño utilizado por el intérprete de línea base y luego se ramifica a ese intérprete como si lo estuviéramos ejecutando todo el tiempo. Para construir este marco de pila se puede utilizar una tabla auxiliar especial guardada por Warp para reconstruir valores que de otro modo no estarían disponibles. [22]
SpiderMonkey está pensado para integrarse en otras aplicaciones que proporcionen entornos de alojamiento para JavaScript. A continuación, se incluye una lista incompleta:
SpiderMonkey incluye un shell de JavaScript para el desarrollo interactivo de JavaScript y para la invocación de archivos de programa de JavaScript desde la línea de comandos. [30]
El shell de JavaScript es un programa de línea de comandos incluido en la distribución fuente de SpiderMonkey. [...] Puede usarlo como un shell interactivo [...] También puede pasar, en la línea de comandos, un archivo de programa JavaScript para ejecutar [...]