Cómo el compilador JIT optimiza código
Cuando se elige un método para la compilación, la JVM introduce los códigos de bytes en el compilador JIT (Just-In-Time). JIT necesita conocer la semántica y la sintaxis de códigos de bytes para poder compilar el método correctamente.
Para que el compilador JIT pueda analizar el método, primero se reformulan los códigos de bytes en una representación interna denominada árboles, que se parece mucho más al código de máquina que los códigos de bytes. A continuación, se realizan análisis y optimizaciones en los árboles del método. Al final, los árboles se convierten en código nativo. El resto de este apartado ofrece una visión general breve de las fases de la compilación JIT. Para obtener más información, consulte Diagnóstico de un problema JIT o AOT.
El compilador JIT puede utilizar más de una hebra para realizar tareas de compilación de JIT. El uso de varias hebras puede ayudar potencialmente a que las aplicaciones Java se inicien más rápido. En la práctica, la compilación JIT de varias muestra mejoras del rendimiento solo donde existen hay núcleos de procesamiento del sistema sin utilizar.
La compilación consta de las fases siguientes. Todas las fases, excepto la generación de código nativo constan de código entre plataformas.
Fase 1 - Incorporación
- Incorporación trivial
- Incorporación de gráficos de llamadas
- Eliminación de recurrencia de cola
- Optimizaciones de protección de llamadas virtuales
Fase 2 - Optimizaciones locales
- Análisis y optimizaciones de flujos de datos locales
- Optimización del uso de registro
- Simplificaciones de lenguajes Java
Fase 3 - Optimizaciones del flujo de control
- Code reordering, splitting y removal
- Loop reduction e inversion
- Loop striding y loop-invariant code motion
- Loop unrolling y peeling
- Loop versioning y specialization
- Optimización dirigida a excepciones
- Análisis de conmutador
Fase 4 - Optimizaciones globales
- Análisis y optimizaciones de flujos de datos globales
- Eliminación de redundancia parcial
- Análisis de secuencias de escape
- Contexto de gráficos y optimizaciones de asignación de memoria
- Optimizaciones de sincronización
Fase 5 - generación de código nativo
Los procesos de generación de código nativo varían, en función de la arquitectura de la plataforma. Por lo general, durante esta fase de la compilación, los árboles de un método se convierten en instrucciones del código de máquina; algunas optimizaciones pequeñas se realizan de acuerdo con las características de la arquitectura. El código compilado se coloca en una parte del espacio de procesos de JVM denominado memoria caché de código; la ubicación del método en la memoria caché de código se registra, para que en futuras llamadas a dicho método se llame al código compilado. En cualquier momento determinado, el proceso de la JVM consta de los archivos ejecutables de JVM y un conjunto de código compilado por JIT que está enlazado dinámicamente al intérprete de códigos de bytes en la JVM.