¿Por qué cambia el valor de typeof null dentro de un bucle?


Ejecutando este fragmento en la consola de Chrome:

function foo() {
    return typeof null === 'undefined';
}
for(var i = 0; i < 1000; i++) console.log(foo());

Debería imprimir 1000 veces false, pero en algunas máquinas imprimirá false para un número de iteraciones, luego true para el resto.

introduzca la descripción de la imagen aquí

¿Por qué sucede esto? ¿Es solo un bicho?

 109
Author: Sergey Novikov, 2016-06-21

4 answers

Hay un error de cromo abierto para esto:

Problema 604033-El compilador JIT no preserva el comportamiento del método

Así que sí, es solo un error!

 74
Author: Slumber86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-21 12:39:46

En realidad es un error del motor JavaScript V8 ( Wiki).

Este motor se utiliza en Chromium, Maxthron, Android OS, Node.js etc.

Relativamente simple descripción del error puedes encontrar en este tema de Reddit :

Los motores JavaScript modernos compilan código JS en código máquina optimizado cuando se ejecuta (compilación Justo a tiempo) para que se ejecute más rápido. Sin embargo, el paso de optimización tiene algún costo de rendimiento inicial en intercambio para un aumento de velocidad a largo plazo, por lo que el motor decide dinámicamente si un método vale la pena dependiendo de la frecuencia con la que se utiliza.

En este caso parece haber un error solo en la ruta optimizada, mientras que el camino no optimizado funciona bien. Así que al principio el método funciona como intención, pero si se llama en un bucle con la suficiente frecuencia en algún momento de la el motor decidirá optimizarlo y reemplazarlo con el buggy versión.

Este error parece haberse solucionado en la propia V8 (commit), así como en Chromium (bug report) y NodeJS (commit).

 37
Author: Sergey Novikov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-22 07:55:37

Para responder a la pregunta directa de por qué cambia, el error está en la rutina de optimización "JIT" del motor JS V8 utilizado por Chrome. Al principio, el código se ejecuta exactamente como está escrito, pero cuanto más lo ejecute, más potencial hay para que los beneficios de la optimización superen los costos del análisis.

En este caso, después de la ejecución repetida en el bucle, el compilador JIT analiza la función y la reemplaza con una versión optimizada. Desafortunadamente, el análisis hace un incorrecto suposición, y la versión optimizada en realidad no produce el resultado correcto.

Específicamente, el usuario de Reddit RainHappens sugiere que es un error en tipo propagación :

También hace alguna propagación de tipos (como en qué tipos puede ser una variable etc). Hay un tipo especial "indetectable" para cuando una variable es indefinida o nula. En este caso el optimizador dice "null es indetectable, por lo que puede ser reemplazado con la cadena" undefined " para el comparación.

Este es uno de los problemas difíciles de optimizar el código: cómo garantizar que el código que se ha reorganizado para el rendimiento siga teniendo el mismo efecto que el original.

 18
Author: IMSoP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-21 15:37:09
 1
Author: user835611,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-29 03:41:36