De nombreux langages dynamiques implémentent (ou souhaitent implémenter) un compilateur JIT afin d'accélérer leurs temps d'exécution. Inévitablement, quelqu'un de la galerie d'arachides demande pourquoi ils n'utilisent pas LLVM. La réponse est souvent "le LLVM ne convient pas à la construction d'un JIT". (Par exemple, le commentaire d'Armin Rigo ici. )
Pourquoi le LLVM ne convient-il pas pour construire un JIT?
Remarque: Je sais que LLVM a son propre JIT. Si LLVM était inadapté, mais convient maintenant, veuillez dire ce qui a changé. Je ne parle pas d'exécuter LLVM Bytecode sur le LLVM JIT, je parle d'utiliser les bibliothèques LLVM pour implémenter un JIT pour un langage dynamique.
Il y a quelques notes sur LLVM dans le billet de blog post-mortem Unladen Swallow: http://qinsb.blogspot.com/2011/03/unladen-swallow-retrospective.html .
Malheureusement, LLVM dans son état actuel est vraiment conçu comme un optimiseur et un back-end de compilateur statique. La génération et l'optimisation de code LLVM sont bonnes mais coûteuses. Les optimisations sont toutes conçues pour fonctionner sur IR généré par des langages statiques de type C. La plupart des optimisations importantes pour l'optimisation Python nécessitent une connaissance de haut niveau de la façon dont le programme s'est exécuté sur les itérations précédentes, et LLVM ne nous a pas aidés à le faire.
Pourquoi le LLVM ne convient-il pas pour créer un JIT?
J'ai écrit HLVM , une machine virtuelle de haut niveau avec un système de type statique riche comprenant des types de valeur, l'élimination des appels de queue, l'impression générique, les threads C FFI et POSIX avec prise en charge de la compilation statique et JIT. En particulier, HLVM offre performances incroyables pour une machine virtuelle de haut niveau. J'ai même implémenté un frontal interactif de type ML avec des types de variantes et une correspondance de modèle à l'aide du compilateur JIT, comme on le voit dans cette démonstration d'algèbre informatique . Tous mes travaux liés à HLVM combinés totalisent seulement quelques semaines de travail (et je ne suis pas un informaticien, juste un dabbler).
Je pense que les résultats parlent d'eux-mêmes et démontrent sans équivoque que LLVM est parfaitement adapté à la compilation JIT.
Il y a une présentation sur l'utilisation de LLVM en tant que JIT, où l'adresse de nombreuses préoccupations soulevées quant à pourquoi son mauvais, la plupart de ses semble se résumer à des personnes construisant un compilateur statique en tant que JIT au lieu de la construction d'un véritable JIT.
Mise à jour: à partir de 7/2014, LLVM a ajouté une fonctionnalité appelée "Points de patch", qui sont utilisés pour prendre en charge les caches polymorphes en ligne dans FTL JavaScript JIT de Safari. Cela couvre exactement le cas d'utilisation dénoncé dans Armin Commentaire de Rigo dans la question d'origine.
Cela prend beaucoup de temps pour démarrer est la plus grande plainte - cependant, ce n'est pas vraiment un problème si vous avez fait ce que Java fait et démarre en mode interprète, et utilise LLVM pour compiler les parties les plus utilisées du programme.
De plus, bien qu'il existe des arguments comme celui-ci dispersés sur Internet, Mono utilise LLVM comme compilateur JIT avec succès depuis un certain temps maintenant (bien qu'il soit intéressant de noter qu'il utilise par défaut son propre backend plus rapide mais moins efficace , et ils ont également modifié des parties de LLVM).
Pour les langages dynamiques, LLVM n'est peut-être pas le bon outil, simplement parce qu'il a été conçu pour optimiser les langages de programmation système comme C et C++ qui sont fortement/statiquement typés et prennent en charge des fonctionnalités de très bas niveau. En général, les optimisations effectuées sur C ne rendent pas vraiment les langages dynamiques rapides, car vous créez simplement un moyen efficace d'exécuter un système lent. Les JIT de langage dynamique modernes font des choses comme les fonctions d'inline qui ne sont connues qu'au moment de l'exécution, ou l'optimisation en fonction du type de variable la plupart du temps, pour lesquelles LLVM n'est pas conçu.
Pour une diatribe plus détaillée sur le LLVM IR, voir ici: LLVM IR est un compilateur IR .