Pregunta

Al diseñar un intérprete de código de byte, ¿hay un consenso en estos días sobre si el formato de la pila o tres direcciones (o algo más?) ¿Es mejor? Estoy mirando estas consideraciones:

  1. El lenguaje objetivo es un lenguaje dinámico bastante similar a JavaScript.

  2. El rendimiento es importante, pero la velocidad de desarrollo y la portabilidad lo son más por el momento.

  3. Por lo tanto, la implementación será estrictamente un intérprete por el momento; Un compilador JIT puede venir más tarde, los recursos permitidos.

  4. El intérprete se escribirá en C.

¿Fue útil?

Solución

Eche un vistazo al intérprete Ocaml Bytecode: es uno de los más rápidos de su tipo. Es prácticamente una máquina de pila, traducida en un código roscado en la carga (usando la extensión GOTO de GNU). También puede generar un código roscado en forma, debe ser relativamente fácil de hacer.

Pero si está teniendo en cuenta una futura compilación JIT, asegúrese de que su máquina de pilas no sea realmente una máquina de pila completa, sino una forma de serialización de árbol de expresión (como .net CLI), de esta manera podría ser capaz Para traducir su bytecodo de "pila" en una forma de 3 direcciones y luego a un SSA.

Otros consejos

Leer La evolución de Lua y La implementación de LUA 5.0 Por cómo Lua cambió de una máquina virtual basada en pila a una máquina virtual basada en registros y por qué obtuvo rendimiento haciéndolo.

Los experimentos realizados por David Gregg y Roberto Ierusalimschy han demostrado que un bytecode basado en registros funciona mejor que un bytecode basado en pila porque se requieren menos instrucciones en bytecode (y, por lo tanto, menos gastos de decodificación) para realizar las mismas tareas. Asi que El formato de tres direcciones es un claro ganador.

No tengo mucha (no ninguna) experiencia en esta área, por lo que es posible que desee verificar algunos de los siguientes por usted mismo (¿o tal vez alguien más puede corregirme cuando sea necesario?).

Los dos idiomas con los que trabajo más hoy en día son C# y Java, por lo que estoy naturalmente inclinado a sus metodologías. Como la mayoría de las personas saben, ambas se compilan en el código de byte, y ambas plataformas (el CLR y el JVM) utilizan JIT (al menos en las implementaciones convencionales). Además, supongo que los nervios para cada plataforma están escritos en C/C ++, pero realmente no lo sé con certeza.

En general, estos idiomas y sus respectivas plataformas son bastante similares a su situación (aparte de la parte dinámica, pero no estoy seguro de si esto importa). Además, dado que son idiomas tan convencionales, estoy seguro de que sus implementaciones pueden servir como una guía bastante buena para su diseño.


Con eso fuera del camino, sé con certeza que tanto el CLR como el JVM son arquitecturas basadas en pila. Algunas de las ventajas que recuerdo para que se basen en Registro basado en Stack

  1. Código generado más pequeño
  2. Intérpretes más simples
  3. Compiladores más simples
  4. etc.

Además, creo que basado en Stack es un poco más intuitivo y legible, pero eso es algo subjetivo, y como dije antes, todavía no he visto demasiado código de byte.

Algunas ventajas de la arquitectura basada en registros son

  1. Se deben ejecutar menos instrucciones
  2. Intérpretes más rápidos (se deduce del #1)
  3. Se puede traducir más fácilmente al código de la máquina, ya que los hardwares más comunes se basan en el registro
  4. etc.

Por supuesto, siempre hay formas de compensar las desventajas para cada una, pero creo que estas describen las cosas obvias a considerar.

Si tiene JIT en su mente, los byteCodes es la única opción.

En caso de que pueda echar un vistazo a mi tiscript: http://www.codeproject.com/kb/recipes/tiscript.aspx y fuentes: http://code.google.com/p/tiscript/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top