¿Cómo se verifica el tipo en un compilador / intérprete de lenguaje dinámico, como JavaScript?

11

En lenguajes dinámicos, como JavaScript o Python, el tipo de una variable se determina en tiempo de ejecución. Esta es una razón por la cual son más lentos que los lenguajes escritos como Java.

¿Cómo se realiza la verificación de tipo? ¿Cuál es la razón esencial por la que este proceso es lento?


fuente
No son más lentos porque son dinámicos, son más lentos porque es más difícil hacerlos más rápidos. JavaScript es en realidad el más optimizado y es bastante rápido.
Derek Litz

Respuestas:

5

Hay confusión en la pregunta.

Se supone que la verificación de tipos es lenta, lo cual no es necesariamente el caso.

La pregunta también parece confundir el proceso de envío de tipos con la verificación de tipos , y son dos cosas diferentes. Uno es un proceso que se realiza en tiempo de ejecución, el otro es un proceso en tiempo de compilación. Sospecho que la pregunta realmente es sobre el envío de tipos.

Es el despacho de tipo el que puede introducir una sobrecarga en tiempo de ejecución, porque el cálculo pasa tiempo con instrucciones que deciden, dinámicamente, qué acción tomar, en función de los tipos de valores que ve en el tiempo de ejecución. por ejemplo, en un lenguaje dinámico, si aplico "+" en dos cosas, podría significar suma numérica o concatenación de cadenas, por lo que necesito pasar tiempo mirando lo que está a la mano para decidir qué hacer. Existen estrategias de evaluación que pueden reducir el costo del despacho dinámico. (por ejemplo, JIT de seguimiento)

Con respecto a la verificación de tipos en JavaScript, consulte: http://www.cs.brown.edu/~sk/Publications/Papers/Published/gsk-flow-typing-theory/ . Para obtener una descripción más general de cómo funcionan los verificadores de tipo, un libro de texto de lenguaje de programación estándar cubrirá los algoritmos. Por ejemplo, http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/

dyoo
fuente
También escribí una pequeña encuesta sobre el rastreo de JIT y lenguajes dinámicos en hashcollision.org/comprehensive/tracing.pdf
El intérprete de Javascript lleva bits de etiqueta con cada valor para el envío de tipo. ¿Podrías elaborar un poco sobre esto? Por ejemplo, ¿de qué sirven los bits de etiqueta? ¿Un bit corresponde a un tipo?
El concepto de un tipo no siempre está conectado a la representación. Podríamos tener un concepto de tipo 'milla' versus tipo 'kilómetro', por ejemplo, y es razonable tener un lenguaje que pueda detectar estáticamente, en el momento de la compilación, si los cálculos están aplicando incorrectamente operaciones en valores que alteran los tipos . Puede imaginar que tendrían la misma representación, y si el compilador puede, en el momento de la compilación, garantizar que nunca se mezclan, entonces no hay ninguna razón por la cual los valores necesitarían un etiquetado adicional en la representación.
1
Continuando: pero a menudo, especialmente en lenguajes dinámicos, desea representar valores de diferentes tipos. Hay varias formas de hacer esta discriminación. Las etiquetas de tipo son comunes, pero existen otras técnicas. Por ejemplo, puede colocar ciertos tipos en regiones de memoria bloqueadas. Consulte "Representación de la información de tipo en lenguajes escritos dinámicamente". lambda-the-ultimate.org/node/3912 para una encuesta exhaustiva de técnicas de representación.
7

Básicamente, en lenguajes sin tipo, cada punto de referencia a un objeto que contiene tanto el tipo como el valor. Por ejemplo, var a = 3apunta a una instancia que contiene el valor 3 y el tipo int, si realiza a = "bla", la referencia se actualiza a una instancia que contiene la cadena "bla" y la cadena de tipo, el objeto antiguo se descarta, etc.

Esto es lento porque cada vez a + bque se debe realizar una operación (por ejemplo ) en este tipo básico, el tiempo de ejecución primero debe desreferenciar los objetos, verificar que su tipo sea compatible, realizar la operación, crear un nuevo objeto.

Por el contrario, a + ben C ++ o Java comprueba en tiempo de compilación que los tipos son válidos y compatibles, a y b se almacenan como valores inmediatos (no referencias), y la adición es una operación de procesador simple en estos valores.

Por supuesto, todo esto es muy teórico. En la práctica, se puede hacer mucha optimización en este proceso para evitar la mayor parte de la sobrecarga, y los lenguajes escritos dinámicamente pueden ser bastante rápidos.

solendil
fuente
1
Trucos como los cachés en línea polimórficos pueden mejorar enormemente el rendimiento. Los escritos de David Ungar (Self) y Eliot Miranda (Squeak, Visual Works Smalltalk virtual machines) son los más informativos sobre el rendimiento dinámico del lenguaje.
Frank Shearar
0

Cada valor se almacena junto con su tipo, que se debe inspeccionar primero. También las conversiones dicen que de una cadena a otra pasan por inspección, sobre la marcha.

Joop Eggen
fuente
Sí, esto es, es solo una verificación de tiempo de ejecución, nada lujoso.
anon