Comment le compilateur JIT optimise-t-il le code ?
Lorsqu'une méthode est choisie pour être compilée, la JVM envoie ses bytecodes au compilateur JIT (Just-In-Time). Le compilateur doit comprendre la sémantique et la syntaxe des bytecodes pour pouvoir compiler correctement la méthode.
Pour permettre au compilateur JIT d'analyser la méthode, ses bytecodes sont reformulés dans une représentation appelé arbres qui ressemble plus au code machine que les bytecodes. Ensuite, l'analyse et les optimisations sont exécutées sur les arbres de la méthode. A la fin, les arbres sont convertis en code natif. Le reste de cette section présente brièvement les phases de la compilation JIT. Pour plus d'informations, voir Diagnostic d'un problème JIT ou AOT.
Le compilateur JIT peut utiliser plusieurs unités d'exécution de compilation pour effectuer les tâches de compilation JIT. L'utilisation de plusieurs unités d'exécution peut potentiellement aider les applications Java à démarrer plus rapidement. En pratique, elle n'améliore les performances que si le système comporte des fichiers core de traitement inutilisés.
Les étapes de la compilation sont les suivantes. Toutes les étapes, à l'exception de la génération du code natif, sont du code interplateformes.
Etape 1 : insertion par référence
- Trivial inlining
- Call graph inlining
- Tail recursion elimination
- Virtual call guard optimizations
Etape 2 : optimisations locales
- l'analyse et l'optimisation du flux de données local
- l'enregistrement de l'optimisation de l'utilisation
- Simplifications des idiomes Java
Etape 3 : optimisations du flux de contrôle
- Code reordering, splitting, and removal
- Loop reduction and inversion
- Loop striding and loop-invariant code motion
- Loop unrolling and peeling
- Loop versioning and specialization
- Exception-directed optimization
- Switch analysis
Etape 4 : optimisations globales
- l'analyse et l'optimisation du flux de données global
- l'élimination de redondance partielle
- l'analyse d'échappement
- les optimisations de la récupération de place et de l'allocation de mémoire
- les optimisations de la synchronisation
Etape 5 : génération du code natif
Les processus de génération du code natif varient en fonction de l'architecture de la plateforme. Généralement, au cours de cette étape de la compilation, les arbres des méthodes sont convertis en instructions en code machine ; de petites optimisations sont exécutées en fonction des caractéristiques de l'architecture. Le code compilé est placé dans une partie de l'espace du processus JVM appelé cache du code ; l'emplacement de la méthode dans le cache du code est enregistré de sorte que les appels suivants à la méthode appellent le code compilé. A tout moment, le processus JVM est constitué des fichiers exécutables JVM et d'un ensemble de code compilé JIT lié dynamiquement à l'interpréteur de bytecode dans la JVM.