Según el código fuente de V8 y los materiales del turboventilador, existe un tipo de desoptimización denominada desoptimización perezosa que se describe a continuación ( v8/src/common/globals.h ):
Perezoso: el código se marcó como dependiente de alguna suposición que se verifica en otro lugar y puede desencadenar la desoptimización la próxima vez que se ejecute el código.
Sin embargo, al observar la ejecución de ' v8/test/mjsunit/compiler/deopt-lazy-shape-mutation.js ' con d8 , descubrí que la desoptimización ocurrió inmediatamente cuando se devolvió desde la función change_o . Supongo que es porque la dependencia del mapa en o of f se socava al ejecutar change_o que manipula la forma de o .
> d8/d8 --trace-deopt --allow-natives-syntax test/deopt-lazy-shape-mutation.js [marking dependent code 0x3d7d00044001 (0x3d7d08293535 <SharedFunctionInfo f>) (opt id 0) for deoptimization, reason: code dependencies] [bailout (kind: deopt-lazy, reason: (unknown)): begin. deoptimizing 0x3d7d08293779 <JSFunction f (sfi = 0x3d7d08293535)>, opt id 0, node id 20, bytecode offset 4, deopt exit 0, FP to SP delta 32, caller SP 0x7ffdaa56ff68, pc 0x3d7d00044111]Mis preguntas son:
¿Qué es exactamente la desoptimización perezosa? En el ejemplo anterior, ¿está bien entender la razón por la que f se desoptimizó tan pronto como se devuelve desde change_o es que change_o marca que se ha comprometido alguna suposición de f ?
¿Cómo se produce la desoptimización perezosa? En el caso de la desoptimización ansiosa , veo que hay nodos llamados Deoptimize* que representan explícitamente la condición de desoptimización inmediata y se ensamblan en código de máquina usando call y saltos condicionales como jnz , ja , etc. Sin embargo, no puedo entender cómo la desoptimización perezosa se activa en el flujo de ejecución. ¿Hay algún supervisor que controle la operación de devolución de call-ret y active la callee cuando el destinatario de la llamada comprometa la dependencia de la persona que caller ?
(Desarrollador V8 aquí.)
- ¿Qué es exactamente la desoptimización perezosa?
Es una desoptimización "programada" de una función que actualmente tiene una o más activaciones en la pila, pero que no es la función que se está ejecutando actualmente (que poseería el marco de la pila superior y realizaría una "desoptimización ansiosa" si fuera necesario) . La desoptimización implica tener que reescribir el contenido del marco de la pila, lo cual es prohibitivamente difícil de hacer para cualquier marco de la pila que no esté en la parte superior, por lo que tales funciones están marcadas para desoptimización y se desoptimizarán tan pronto como el control regrese a ellas (es decir, cuando se conviertan en las más altas). marco de pila).
Tenga en cuenta que la misma función puede desoptimizarse tanto con entusiasmo (para su activación en ejecución) como con pereza (para cualquier activación adicional más abajo en la pila).
En el ejemplo anterior, ¿está bien entender la razón por la que
fse desoptimizó tan pronto como se devuelve desdechange_oes quechange_omarca que se ha comprometido alguna suposición def?
Sí. change_o invalida una suposición que se hizo cuando f se optimizó anteriormente. (Cualquier optimización posterior de f no hará la misma suposición).
- ¿Cómo se produce la desoptimización perezosa?
Las direcciones de retorno en la pila se reescriben, por lo que en lugar de reanudar la ejecución del código original, se inicia la secuencia de desoptimización. Consulte class ActivationsFinder en deoptimizer.cc si desea profundizar en los detalles.