[Conocimiento profundo del compilador JIT de la máquina virtual Java] 1151 Conocimiento profundo del compilador Graal

1. Antecedentes históricos

1. La máquina virtual Graal y el compilador Graal aún no están disponibles comercialmente en el laboratorio, pero se espera que reemplacen o se conviertan en la base de la próxima generación de tecnología HotSpot en el futuro. El compilador Graal fue diseñado originalmente en la máquina virtual Maxine [ilustración] como el compilador de próxima generación del compilador C1X [ilustración], por lo que, por supuesto, está escrito en el lenguaje Java.

2. En 2012, el compilador de Graal se separó del proyecto de máquina virtual Maxine y se convirtió en un proyecto de compilador de Java desarrollado de forma independiente.

3. El compilador de Graal se agregó por primera vez al JDK oficial en forma de una herramienta de precompilación de Jaotc en JDK 9. A partir de JDK 10, el compilador de Graal puede reemplazar el compilador del lado del servidor y convertirse en la compilación justo a tiempo de nivel superior en la compilación en capas de HotSpot Dispositivo. La realización de esta arquitectura de compilador alternativa justo a tiempo se beneficia de la aparición de la interfaz del compilador HotSpot.

4. En los primeros días de Graal, como C1 y C2, la colaboración con HotSpot estaba estrechamente ligada, lo que significaba que cada vez que se compilaba Graal, todo el HotSpot tenía que volver a compilarse. JEP 243: Java-Level JVM Compiler Interface (JVMCI), lanzado en JDK 9, permite que Graal se separe del código de HotSpot.

5. Tres funciones de JVMCI

R: Responda a la solicitud de compilación de HotSpot y distribuya la solicitud al compilador Just-In-Time implementado por Java.

B: permite al compilador acceder a estructuras de datos relacionadas con la compilación JIT en HotSpot, incluidas clases, campos, métodos y datos de supervisión del rendimiento, etc., y proporciona un conjunto de representaciones abstractas de estas estructuras de datos a nivel de lenguaje Java.

C: proporciona la representación abstracta del lado Java del caché de código HotSpot, lo que permite al compilador implementar el código de máquina binario compilado.

Con las tres funciones, un compilador just-in-time (no limitado a Graal) implementado en lenguaje Java fuera de la máquina virtual HotSpot se puede integrar en HotSpot, respondiendo a la solicitud de compilación de nivel superior emitida por HotSpot y convirtiendo el código binario compilado Implementar en la caché de código de HotSpot.

6. La aparición de Graal y JVMCI, para lectores que no están directamente involucrados en el desarrollo de la máquina virtual y el compilador Java, pero que sienten curiosidad por la tecnología de la máquina virtual Java, proporciona una buena manera de espiar y probar la tecnología del compilador. Graal está aquí para combatir el proceso de optimización de código y compilación en tiempo real de la máquina virtual HotSpot.

Dos, crear un entorno de compilación y depuración

1. Con el fin de reducir la complejidad de la gestión de código, gestión de dependencias, compilación y pruebas, el equipo de Graal escribió una pequeña herramienta llamada mx en Python 2 para automatizar estas cosas.

2. Instale mx primero

# git clone https://github.com/graalvm/mx.git
# 倒入环境变量
export PATH = 'pwd'/mx:$PATH

Descripción

Encuentre un JDK adecuado para compilar. Teniendo en cuenta que el proyecto Graal VM se desarrolla en base a OpenJDK 8, y la interfaz JVMCI se proporcionará después de JDK 9, el equipo de Graal ha proporcionado una versión OpenJDK 8 con función JVMCI. Podemos elegir esta versión de JDK 8 para compilar . Cuando los lectores solo prestan atención a la aplicación del compilador Graal en HotSpot y no quieren involucrar otros aspectos de Graal VM, pueden usar directamente JDK 9 y el estándar Open / OracleJDK posterior.

Debe modificar el montón de Java utilizado en la configuración del IDE a 2 GB o más para asegurarse de que la compilación y construcción de Graal en el IDE pueda realizarse sin problemas.

3. Configure las variables de entorno correspondientes a la versión de Java.

export JAVA_HOME=/usr/lib/jvm/oraclejdk1.8.0...

4, es obtener el código del compilador Graal

# git clone https://github.com/graalvm/graal.git
# cd /graal/comiler
# mx build

Tres, interfaz de compilador JVMCI

1. El contenido principal de la interfaz JVMCI es en realidad

Bytecode, el número de ranuras de variables en la tabla de variables, la profundidad máxima de la pila de operandos y la información estadística recopilada en la parte inferior de la compilación en capas.

2. Interfaz

interface JVMCICompiler {
    
}

interface CompliationRequest {
    
}

interface JavaMethod {
    
}

Cuarto, la representación del medio del código

1. El código está dentro del compilador

El proceso de transformación de bytecode → gráfico ideal → optimización → código de máquina (representado por Mach Node Graph).

2. Un gráfico ideal es un gráfico dirigido, los nodos se utilizan para representar elementos del programa, como variables, operadores, métodos, campos, etc., mientras que los bordes se utilizan para representar datos o controlar el flujo.

R: El autor usa la línea azul (indicada por la línea punteada) para el flujo de datos y la línea roja (indicada por la línea continua) para el flujo de control)

B: El gráfico ideal es esencialmente una representación gráfica que combina el gráfico de flujo de datos y el gráfico de flujo de control de cierta manera, usando un borde para representar el flujo de datos y el otro borde para representar el flujo de control.

Inserte la descripción de la imagen aquí

Cómo se envían el parámetro 0 (denotado como P (0)) y el parámetro 1 (denotado como P (1)) a la operación de suma, y ​​luego cómo se envía el resultado a la operación de división junto con la constante 2 (denotado como C (2)) .

3. Eliminación de expresiones de palabras comunes
Inserte la descripción de la imagen aquí

Inserte la descripción de la imagen aquí

Inserte la descripción de la imagen aquí

Cinco, optimización y generación de código

1. Cada nodo de un gráfico ideal tiene dos operaciones principales en común, una es Canonicalización y la otra es Generación.

2. La estandarización se refiere a cómo reducir la escala del gráfico ideal, es decir, las medidas a tomar para optimizar el código en base al gráfico ideal.

3. Si en el gráfico se encuentra una subexpresión aritmética que se puede eliminar, busque el nodo duplicado, reemplácelo y elimínelo.

ejemplo:

La simple operación de sumar dos enteros también ha probado el plegamiento constante (si ambos operandos son constantes, se devuelve un nodo constante directamente), agregación aritmética (nodos secundarios constantes del árbol de agregación, como (a + 1) +2 agregados en a + 3), fusión de signos (los subnodos de signo opuesto del árbol de agregados, por ejemplo, fusionan directamente (ab) + bo b + (ab) en a) y muchas otras optimizaciones.

4. Graal no se convierte directamente del gráfico ideal al código de máquina, pero al igual que otros compiladores, primero generará una representación intermedia de bajo nivel (LIR, una representación intermedia relacionada con el conjunto de instrucciones de la máquina específico), y luego el backend unificado HotSpot Genere código de máquina.

Para operaciones que involucran suma aritmética, se realiza en el método emitAdd () de la interfaz ArithmeticLIRGeneratorTool

5. Plataformas de destino compatibles con el compilador Graal

Actualmente, solo proporciona representaciones intermedias de bajo nivel de los conjuntos de instrucciones de las tres plataformas de destino (SPARC, x86-AMD64, ARMv8-AArch64).

6. La normalización no se limita al ámbito local de un solo código de operación. Muchas optimizaciones se basan en la situación general. Este tipo de operación se completa en la clase CanonicalizerPhase.

Supongo que te gusta

Origin blog.csdn.net/qq_40996741/article/details/109173594
Recomendado
Clasificación