web-dev-qa-db-fra.com

Pourquoi la valeur de typeof null change-t-elle à l'intérieur d'une boucle?

Exécution de cet extrait dans la console Chrome:

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

devrait imprimer 1000 fois false, mais sur certaines machines, false sera imprimé plusieurs fois, puis true pour le reste.

enter image description here

Pourquoi cela arrive-t-il? Est-ce juste un bug?

109
Agos

Il y a un bug de chrome ouvert pour cela:

Problème 604033 - Le compilateur JIT ne conserve pas le comportement de la méthode

Alors oui, c'est juste un bug!

74
Slumber86

C’est en fait un bug V8 du moteur JavaScript ( Wiki ).

Ce moteur est utilisé dans Chrome, Maxthron, Android OS, Node.js etc.

Relativement simple description du bogue vous pouvez trouver dans ce sujet Reddit :

Les moteurs JavaScript modernes compilent le code JS en un code machine optimisé lors de son exécution (compilation Just In Time) pour accélérer son exécution. Cependant, l’optimisation a un coût de performance initial en contrepartie d’une accélération à long terme. Le moteur décide donc dynamiquement si une méthode en vaut la peine, en fonction de la fréquence à laquelle elle est utilisée.

Dans ce cas, il semble y avoir un bogue uniquement dans le chemin optimisé, alors que le chemin non optimisé fonctionne correctement. Ainsi, au début, la méthode fonctionne comme prévu, mais si elle est appelée dans une boucle assez souvent, le moteur décide de l'optimiser et de la remplacer par la version buggy.

Ce bogue semble avoir été corrigé dans la V8 ( commit ), ainsi que dans Chromium ( rapport de bogue ) et NodeJS ( commit ).

37
Sergey Novikov

Pour répondre à la question directe de savoir pourquoi cela change, le bogue se trouve dans la routine d'optimisation "JIT" du moteur V8 JS utilisé par Chrome. Au début, le code est exécuté exactement comme il a été écrit, mais plus vous l'exécutez, plus les avantages de l'optimisation l'emportent sur les coûts de l'analyse.

Dans ce cas, après une exécution répétée dans la boucle, le compilateur JIT analyse la fonction et la remplace par une version optimisée. Malheureusement, l'analyse émet une hypothèse incorrecte et la version optimisée ne produit pas le résultat correct.

Plus précisément, RainHappens suggère par Reddit qu'il s'agit d'une erreur dans la propagation du type :

Il effectue également une propagation de type (comme dans quels types une variable, etc., peut être). Il existe un type spécial "indétectable" pour les variables indéfinies ou nulles. Dans ce cas, l'optimiseur indique que "null est indétectable, il peut donc être remplacé par la chaîne" indéfinie "pour la comparaison.

C’est l’un des problèmes majeurs de l’optimisation du code: comment garantir que le code qui a été réorganisé pour obtenir des performances aura toujours le même effet que le code original.

18
IMSoP
1
user835611