BitrootBlog
Retour au site ↗
© 2026 Bitroot · Le contenu est fourni à titre informatif et ne constitue pas un conseil financier, juridique, fiscal ou d'investissement.
Charte éditorialeRetour au site
← Tous les articles
Fondamentaux EVM·2026/10/09·Environ 19 min

L'EVM dans les clients : interpréteurs, JIT et tour d'horizon de revm/evmone

Le client d'exécution traite l'EVM comme un exécuteur remplaçable, séparé par une couche d'accès à l'état. L'interpréteur intégré de go-ethereum, evmone et revm occupent des positionnements différents ; la cohérence entre implémentations repose sur les vecteurs de test issus de la spécification, et l'espace d'optimisation de l'interpréteur se concentre sur la distribution, la facturation du gaz et la gestion de la mémoire.

By Bitroot Core Team · Editorial standards

Un client d'exécution (execution client) doit gérer en même temps la synchronisation des blocs, le pool de transactions, le stockage de l'état, le JSON-RPC et l'interface avec le consensus ; la machine virtuelle Ethereum (Ethereum Virtual Machine, EVM) n'en est qu'un morceau. L'EVM ne sait pas d'où viennent les blocs et ne décide pas non plus quelle règle fixe le prix du gaz d'une transaction : elle reçoit du bytecode, des données d'appel, un environnement d'exécution et du gaz, et renvoie des données de retour, du gaz restant, un état d'exception et un ensemble de changements d'état.

Ce n'est qu'en traçant clairement cette frontière que l'on comprend pourquoi go-ethereum, evmone et revm occupent des positions différentes : l'un est un interpréteur intégré à un client, l'autre une bibliothèque autonome multi-langage, le troisième un framework Rust importé comme dépendance. Ce qui suit ne traite que de l'intégration de l'EVM dans les clients généralistes et des moyens de garantir la cohérence entre plusieurs implémentations ; il n'aborde pas l'ordonnancement parallèle ni la conception multi-moteur, points renvoyés à la section « Pour aller plus loin » en fin d'article.

La frontière entre l'EVM et le reste du client

Quelle que soit l'implémentation, les interactions entre l'EVM et son hôte se ramènent au même ensemble d'opérations : lire le solde, le nonce et le code d'un compte, lire un slot de stockage, lire le hachage d'un bloc historique ; réécrire des changements de stockage, émettre des logs, créer ou supprimer des comptes ; et enfin encaisser ou débourser du gaz. La seule différence tient à la forme sous laquelle cet ensemble d'opérations est exposé.

Le core/vm de go-ethereum implémente l'EVM sous la forme d'une structure plus une boucle d'interpréteur. L'interpréteur choisit selon le fork une table de saut (jump table) de 256 entrées, chaque entrée contenant la fonction d'exécution, le gaz constant, la fonction de calcul du gaz dynamique, les contraintes de hauteur de pile et les besoins en mémoire. L'ordre de la boucle est le suivant : récupérer l'opcode, valider la pile, débiter le gaz constant, calculer le gaz dynamique, étendre la mémoire si nécessaire, appeler la fonction d'exécution ; en cas de gaz insuffisant, ErrOutOfGas est renvoyé uniformément. Les accès à l'état passent par StateDB, le contexte de bloc et de transaction par BlockContext et TxContext. Le gaz intrinsèque, la validation du nonce, la déduction des frais et le calcul des remboursements ne sont pas dans l'interpréteur, mais effectués dans la couche de transition d'état.

La structure de revm est plus explicite : Evm se compose d'un Context et d'un constructeur, et le Context lui-même se décompose en trois blocs, l'environnement (Transaction, Block, Cfg), le Journal et la Database. Database est une interface qui ne comporte que quatre méthodes obligatoires : basic lit un compte, code_by_hash lit du code, storage lit un slot de stockage, block_hash lit le hachage d'un bloc historique. Ces données sont lues puis mises en cache dans le Journal ; le Journal enregistre également les changements survenus pendant l'exécution et restitue les différences d'état à la fin. L'interpréteur ne touche pas directement la base de données : il y accède via le trait Host, organisé par blocs, transactions, configuration, base de données et Journal, et couvrant sload, sstore, tload, tstore, le chargement de comptes, les logs et l'auto-destruction.

evmone fait de cette frontière une ABI en langage C. Il implémente EVMC (Ethereum Client-VM Connector API), une interface définie comme l'ABI de bas niveau entre l'EVM et le client, et qui fixe côté client la manière dont l'EVM accède à l'environnement et à l'état. La frontière étant une ABI C, evmone peut être chargé par des clients écrits dans d'autres langages ; le retour d'expérience d'Erigon mentionne qu'il a intégré evmone à sa propre couche d'exécution via EVMC, en ajoutant une couche de code C++ pour réduire le coût de l'interface.

Les différences de positionnement des trois implémentations

ImplémentationLangage et licenceFormeInterface d'étatMode de réutilisation typique
go-ethereum core/vmGo, code de bibliothèque LGPL-3.0, GPL-3.0 pour cmd/Interpréteur intégré au clientStateDBForké comme client d'exécution L2, par exemple op-geth d'OP Stack
evmoneC++20, Apache-2.0Module autonome, exposé via EVMCInterface hôte EVMCChargé comme module d'exécution par des clients comme Silkworm
revmRust, MITBibliothèque et framework, découpé en cratesTraits Database et HostDépendance directe pour Reth, Foundry, Helios, etc., et choix courant pour les L2 et les zkVM

Ces trois formes correspondent à trois arbitrages d'ingénierie. Un interpréteur intégré peut être optimisé avec sa propre couche d'état, sa table de saut et ses traceurs, au prix d'une réutilisation difficile par d'autres clients. Une bibliothèque autonome est réutilisable entre langages, mais doit traverser une interface générique dont le coût d'appel des deux côtés constitue une charge. Le même retour d'expérience indique que la conception d'EVMC autorise l'hôte à appeler l'EVM et l'EVM à rappeler l'hôte ; ce second sens a entraîné un coût d'interface considérable lors de l'intégration à Erigon via CGo, qu'il a fallu compenser par du code C++ supplémentaire. Cette expérience montre que brancher l'EVM le plus rapide dans un client et rendre ce client immédiatement plus rapide sont deux choses différentes.

Les bénéfices de la forme bibliothèque sont plus visibles à l'échelle de l'écosystème. La documentation de revm cite parmi ses utilisateurs des constructeurs de blocs, des clients comme Reth et Helios, des outils comme Foundry et Hardhat, plusieurs L2 et divers projets zkVM. À l'inverse, la voie du fork de go-ethereum montre des signes de repli du côté des L2 : la documentation d'Optimism indique qu'op-geth a cessé d'être pris en charge le 31 mai 2026 et ne prend pas en charge le hard fork Karst actuellement activé, le client d'exécution mis en avant devenant op-reth, fondé sur Reth et revm.

La cohérence ne se prouve pas par autotest : state test et tests multi-clients

Le consensus exige que tous les nœuds aboutissent exactement au même état pour un même segment de bytecode. Un autotest mené sur un seul client ne peut prouver que sa cohérence interne, pas la cohérence entre implémentations.

Le coût historique des divergences peut se quantifier. Le 24 novembre 2016, Ethereum a connu un fork au bloc 2 686 351 : lorsque des transactions provoquant la suppression de comptes vides se terminaient en out-of-gas, go-ethereum n'annulait pas ces suppressions, alors que Parity les annulait. La chaîne minoritaire a été abandonnée vers le bloc 2 686 516, rendant caduque la production d'environ 165 blocs ; go-ethereum a corrigé son mécanisme de journalisation en v1.5.3 pour s'aligner sur le comportement de Parity, et la communication officielle signale en outre que Parity présentait aussi une divergence dans le cas plus étroit d'un « appel out-of-gas à un contrat précompilé ». Cette révision a ajouté à l'EIP-161 la précision que « lors d'un rollback d'état, la suppression des comptes vides doit elle aussi être annulée ». Le code client conserve une autre trace du même genre : le journal d'état de go-ethereum garde un marqueur explicite de touch pour l'adresse de précompilé RIPEMD160 0x03, et un commentaire du code source précise qu'il sert à reproduire le cas particulier de touch/revert de compte vide du bloc 1 714 175. Ces compatibilités codées en dur entre spécification et implémentation perdureront, et c'est aussi pourquoi la cohérence entre implémentations doit être vérifiée cas par cas.

La réponse de l'industrie consiste à faire venir la spécification et les vecteurs de test de la même source. La spécification de la couche d'exécution est maintenue sous forme d'implémentation de référence en Python (Execution Layer Specification, souvent appelée EELS), et le framework de test génère les vecteurs de test (fixtures) à partir de la spécification. execution-spec-tests était à l'origine un framework Python et un ensemble de cas générant les vecteurs de test ; en novembre 2025, l'ensemble a migré dans ethereum/execution-specs (l'ancien dépôt a ensuite été archivé), la communication officielle précisant que l'emplacement de publication des fixtures pour les clients ne change pas, spécification et tests venant désormais de la même source.

Le mode de décision d'un state test est très direct : étant donné un état avant exécution pre, un environnement env, une transaction transaction et un résultat attendu post découpé par fork, le client doit, après avoir appliqué la transaction, correspondre à la racine d'état hash et au résumé des logs logs enregistrés dans post ; pour les transactions censées échouer, expectException décrit le type d'exception attendu. Les block tests couvrent en plus le traitement au niveau du bloc. Ces vecteurs peuvent être exécutés directement via l'entrée de test propre à chaque client : go-ethereum avec evm statetest, Besu avec evmtool state-test, Nethermind avec nethtest, evmone avec evmone-statetest et evmone-blockchaintest ; ils peuvent aussi être placés dans Hive, qui envoie des charges utiles de blocs aux clients via l'Engine API et vérifie les réponses et la synchronisation d'état, la forme de test la plus proche du comportement de production. Le dépôt hive-tests d'ethpandaops transforme ces tests en pipeline exécuté quotidiennement, couvrant Besu, Erigon, EthereumJS, Ethrex, go-ethereum, Nethermind, Nimbus-EL et Reth.

Il faut aussi préciser les limites des tests. Ils ne couvrent que des comportements déjà écrits : chaque nouveau fork ajoute une fenêtre que les vecteurs ne fixent pas encore. Ils contraignent la sémantique observable, pas la performance, ni la structure interne.

La distribution des instructions : table de saut, switch généré et inlining

La boucle principale de l'interpréteur doit, pour chaque instruction exécutée, localiser d'abord sa fonction de traitement. La table de saut procède par une consultation d'un tableau de 256 entrées, puis un appel via un pointeur de fonction. Go ne peut pas inliner à travers une valeur de fonction : chaque instruction paie donc un chargement dans le tableau plus un appel indirect.

go-ethereum a soumis en 2026 un changement transformant la distribution en switch généré (PR #35144, puis la PR #35638 qui la remplace). Un switch dense sur l'octet d'opcode est compilé en table de saut, et le compilateur peut inliner dans la boucle les fonctions de traitement des cas chauds. Le changement comporte trois niveaux : les opcodes chauds dont le comportement est stable entre forks deviennent des case à part, le gaz constant et les bornes de pile étant écrits directement en constantes ; la minorité d'opcodes à gaz dynamique mais invariants entre forks passe toujours par la facturation par table, mais appelle les fonctions de traitement par leur nom ; tous les opcodes qui varient selon le fork (CALL, CREATE, SSTORE, SLOAD, les logs et les opcodes de copie) continuent d'être distribués via la table du fork courant. La boucle d'interpréteur d'origine est conservée comme implémentation de référence, et les tests exécutent les deux boucles en parallèle en comparant sorties, gaz, erreurs, remboursements, logs et racine d'état, avec en plus un fuzzing différentiel sur du bytecode arbitraire.

Les chiffres donnés par le benchmark A/B de la PR #35638 sont les suivants, dans les conditions de 2 000 blocs du mainnet (blocs 25 677 501 à 25 679 500), sur la machine geth-benchmark-1, avec go1.27.0 et 3 exécutions par côté : le débit passe de 391,2 MGas/s à 424,9 MGas/s, la durée moyenne de newPayload de 71,6 ms à 65,1 ms, et le p50 de la phase d'exécution de 37,47 ms à 31,58 ms. Au 18 septembre 2026, cette PR est toujours open sur GitHub et n'a pas été fusionnée : ces chiffres relèvent donc d'un benchmark interne à la PR, et non d'une mesure de version publiée, et doivent être cités comme à vérifier.

evmone a pris une autre voie. Son interpréteur baseline par défaut ne fait que l'analyse la plus élémentaire des JUMPDEST ; l'interpréteur advanced optionnel utilise le filage d'appels indirects (indirect call threading) : il représente le programme EVM chargé comme une table de pointeurs vers les fonctions implémentant les instructions virtuelles, précalcule le gaz et les besoins de pile par bloc de base, et effectue une seule vérification à l'entrée du bloc. Le coût est une analyse de bytecode plus lourde avant l'exécution.

Facturation du gaz : séparation du constant et du dynamique, accès froids et chauds facturés au slot

L'interpréteur doit calculer les frais avant d'exécuter l'opcode. go-ethereum les sépare en une partie constante et une partie dynamique : le gaz constant est débité directement, le gaz dynamique est calculé par la fonction de traitement en fonction de la pile, de la mémoire et de l'état ; le coût d'extension de la mémoire croît de façon superlinéaire avec le nombre de mots requis, si bien que l'interpréteur doit d'abord calculer la taille de mémoire exigée par l'opcode, puis facturer.

Depuis l'EIP-2929, la facturation du gaz et la couche d'accès à l'état sont liées. Cette proposition impose à chaque transaction de maintenir deux ensembles, les adresses déjà accédées et les slots de stockage déjà accédés, le type d'élément des slots de stockage étant Set[Tuple[Address, Bytes32]] ; le premier accès à un slot coûte COLD_SLOAD_COST, soit 2 100 gaz, un accès répété coûte WARM_STORAGE_READ_COST, soit 100 gaz, et le premier accès à une adresse coûte COLD_ACCOUNT_ACCESS_COST, soit 2 600 gaz. Les ensembles d'accès appartiennent au contexte de transaction et sont détenus physiquement par l'environnement d'exécution du client ; l'interpréteur doit revenir les consulter et les mettre à jour à chaque SLOAD ou appel. C'est aussi pourquoi il est difficile de modifier l'interpréteur indépendamment de la couche d'état.

Le précalcul du gaz par bloc a des effets de bord observables. La documentation d'evmone l'indique clairement : parce que les besoins de tout le bloc de base sont vérifiés à l'avance, il peut apparaître des opérations visibles de l'extérieur qui s'exécuteraient avec une facturation instruction par instruction mais pas avec une facturation anticipée ; la documentation estime que cela ne pose pas de problème de consensus, l'exécution se terminant par une exception dure et tous les effets étant annulés, mais cela peut produire des traces d'exécution différentes ou se terminer par un type d'exception différent. Ces écarts tombent précisément dans le périmètre contraint par les vecteurs de test.

Mémoire et cadres d'appel : sortir l'allocation du chemin chaud

Chaque appel de contrat a besoin de pile et de mémoire. La pile de l'EVM est plafonnée à 1 024 entrées, la mémoire s'étend à la demande et est facturée, et les données de retour nécessitent aussi un tampon. Ces objets ont une durée de vie courte et une fréquence de création élevée, si bien que les implémentations privilégient généralement la réutilisation plutôt qu'une allocation à chaque fois : go-ethereum crée un objet Memory à l'entrée de l'interpréteur et l'étend mot par mot lorsque l'opcode exige davantage de mémoire ; la couche de contexte de revm détient un FrameStack avec mise en commun d'éléments (item-pooling), qui réutilise les cadres d'appel par index.

Précompilés : implémentations natives et arbitrages de dépendances

Les contrats précompilés sont des implémentations natives situées à quelques adresses fixes ; à l'exécution, c'est l'hôte qui calcule directement, sans interpréter de bytecode, l'interpréteur ne se chargeant que du routage et de la facturation du gaz, et le coût de certains précompilés dépendant aussi de la longueur de l'entrée.

Les arbitrages des bibliothèques autonomes à ce niveau méritent un examen à part. La documentation d'evmone expose deux compromis : ecrecover est implémenté par evmone lui-même, avec une perte de performance ; expmod utilise par défaut une implémentation factice qui ne répond correctement que pour des entrées connues, et obtenir l'implémentation complète exige d'activer EVMONE_PRECOMPILES_GMP=1 à la compilation, en introduisant GMP comme dépendance de build et d'exécution. Cela reflète un problème général : la correction d'un précompilé doit valoir pour des entrées arbitraires, et aligner bit à bit avec les autres implémentations du code natif comme l'arithmétique de grands entiers, la récupération sur courbe elliptique et le hachage Keccak est en soi un endroit propice aux divergences.

Pourquoi la compilation JIT n'est pas devenue le choix dominant

La compilation JIT (just-in-time compilation) dans les clients EVM n'a connu qu'une seule tentative officielle : ethereum/evmjit, fondé sur LLVM, compilait le code des contrats en code machine à l'exécution pour remplacer l'EVM à interpréteur du client. Ce dépôt est désormais archivé, et son README précise que le projet n'est plus maintenu et ne doit être utilisé pour rien d'important.

Le README n'explique pas les raisons de l'arrêt de la maintenance, mais plusieurs obstacles apparaissent du point de vue technique. Les cibles de saut de l'EVM proviennent de valeurs présentes sur la pile, le code peut être lu à l'exécution et la structure du programme ne se détermine qu'au moment de l'exécution : le compilateur a donc beaucoup de mal à obtenir à la compilation un graphe de flot de contrôle stable, comme il le fait dans la JVM. La quantité de calcul disponible pour un seul appel est en outre bornée par le plafond de gaz du bloc, ce qui plafonne le gain total. Une alternative relativement mature consiste à déplacer l'analyse au stade statique : EOF (EVM Object Format, EIP-7692) est une tentative dans cette direction, avec un format de conteneur, des sauts relatifs statiques, une validation de pile et une séparation des segments de code et de données. Mais cette voie n'est aujourd'hui pas active : EOF a été retiré du périmètre de la mise à niveau Fusaka le 28 avril 2025, la PR #9703 des EIP ayant été fusionnée le jour même pour ne couvrir que ce retrait de l'étape Fusaka ; l'EIP-7692 lui-même a le statut stagnant, et il ne figure pas non plus dans la liste officielle du périmètre de Glamsterdam, l'EIP-7773. Le journal des changements du site de suivi tiers eipsinsight montre que l'EIP-7692 a été retiré du panier de candidats lors du tri du périmètre de Glamsterdam le 27 août 2026, cette dernière information ne venant que d'une source tierce. À court terme, le principal terrain d'optimisation des clients généralistes reste donc l'interpréteur, et l'exécution compilée n'a pas encore d'espace où s'implanter.

Dans quelles conditions ces optimisations ne portent pas

Les gains décroissent dès que l'exécution n'est plus le poste dominant. Dans le benchmark go-ethereum cité plus haut, le p50 de la phase d'exécution passe de 37,47 ms à 31,58 ms, tandis que le p50 du temps total par bloc passe de 62,1 ms à 56,2 ms : toujours selon le même tableau, la lecture d'état, le hachage d'état et la validation (commit) représentent ensemble environ un tiers du temps total, et près de la moitié si l'on ajoute les frais de la couche moteur ; le plafond des optimisations de l'interpréteur est fixé par cette proportion. Plus la charge penche vers l'accès à l'état et les E/S disque, plus le gain marginal d'une optimisation de l'interpréteur est faible.

Les différences entre forks empêchent d'appliquer les optimisations partout. La table de saut est générée par fork, et le switch généré ne peut lui aussi inliner que les opcodes dont le comportement est stable entre forks ; les opcodes dont les métadonnées varient selon le fork doivent rester sur le chemin de distribution par table, faute de quoi des constantes erronées seraient écrites.

Les contraintes sémantiques délimitent le périmètre des optimisations. Une optimisation ne doit pas changer l'ordre des logs, l'ordre des hooks de traçage, le type des exceptions ni la facturation du gaz, autant d'éléments fixés par les vecteurs de test. L'exemple d'evmone où la vérification anticipée au niveau du bloc de base peut terminer l'exécution plus tôt est précisément le lieu où une optimisation et la sémantique observable exigent un arbitrage explicite.

Le coût de la cohérence augmente avec le nombre d'implémentations. Chaque implémentation supplémentaire ajoute un point de divergence possible sur la frontière du consensus ; les vecteurs de test peuvent comprimer cette surface, mais pas l'éliminer. La valeur de redondance apportée par plusieurs implémentations et ce coût sont les deux extrémités du même arbitrage.

Sources

  • Documentation revm, Introduction : https://bluealloy.github.io/revm/
  • Documentation revm, Architecture : https://bluealloy.github.io/revm/architecture.html
  • revm, trait Database : https://docs.rs/revm/latest/revm/context/trait.Database.html
  • revm, trait Host : https://docs.rs/revm-interpreter/latest/revm_interpreter/trait.Host.html
  • Dépôt revm et liste des utilisateurs : https://github.com/bluealloy/revm
  • Description du dépôt evmone (interpréteurs baseline et advanced, arbitrages sur les précompilés) : https://github.com/ethereum/evmone
  • evmone, Efficient gas calculation algorithm for EVM : https://github.com/ethereum/evmone/blob/master/docs/efficient_gas_calculation_algorithm.md
  • EVMC, Ethereum Client-VM Connector API : https://github.com/ethereum/evmc
  • Retour d'expérience sur les origines du projet Silkworm (coût d'interface d'EVMC et de CGo) : https://erigon.substack.com/p/staged-sync-and-short-history-of
  • Boucle d'interpréteur de go-ethereum : https://github.com/ethereum/go-ethereum/blob/master/core/vm/interpreter.go
  • Définition de la table de saut de go-ethereum : https://github.com/ethereum/go-ethereum/blob/master/core/vm/jump_table.go
  • PR #35638 de go-ethereum (switch généré et inlining PGO, avec les conditions du benchmark) : https://github.com/ethereum/go-ethereum/pull/35638
  • Dépôt go-ethereum et informations de licence : https://github.com/ethereum/go-ethereum
  • Couche de transition d'état de go-ethereum (gaz intrinsèque, validation du nonce, remboursements) : https://github.com/ethereum/go-ethereum/blob/master/core/state_transition.go
  • Livre jaune d'Ethereum (fonction de coût d'extension de la mémoire) : https://ethereum.github.io/yellowpaper/paper.pdf
  • EIP-2929, Gas cost increases for state access opcodes : https://eips.ethereum.org/EIPS/eip-2929
  • Dépôt execution-specs (spécification et vecteurs de test) : https://github.com/ethereum/execution-specs
  • The Weld is Complete (annonce de la fusion d'execution-spec-tests) : https://steel.ethereum.foundation/blog/2025-11-04_weld_final/
  • Description du format des state tests : https://steel.ethereum.foundation/docs/execution-specs/running_tests/test_formats/state_test/
  • Exécution directe des vecteurs de test et entrées de chaque client : https://steel.ethereum.foundation/docs/execution-specs/running_tests/consume/direct/
  • ethpandaops/hive-tests (tests de cohérence multi-clients quotidiens) : https://github.com/ethpandaops/hive-tests
  • Avis de sécurité de la Fondation Ethereum, défaut de consensus du 24 novembre 2016 : https://blog.ethereum.org/2016/11/25/security-alert-11242016-consensus-bug-geth-v1-4-19-v1-5-2
  • Notes de version de go-ethereum v1.5.3 : https://github.com/ethereum/go-ethereum/releases/tag/v1.5.3
  • Dépôt ethereum/evmjit (archivé) : https://github.com/ethereum/evmjit
  • EIP-7692, EVM Object Format (EOFv1) Meta : https://eips.ethereum.org/EIPS/eip-7692
  • Explication du retrait d'EOF par l'EIP-7607 (PR #9703 des EIP) : https://github.com/ethereum/EIPs/pull/9703
  • EIP-7773, Hardfork Meta - Glamsterdam (liste officielle du périmètre, sans EOF) : https://eips.ethereum.org/EIPS/eip-7773
  • Documentation Optimism, annonce de fin de prise en charge d'op-geth : https://docs.optimism.io/notices/op-geth-deprecation
  • Site de suivi tiers eipsinsight, périmètre de la mise à niveau Glamsterdam et journal des changements : https://eipsinsight.com/upgrade/glamsterdam

Pour aller plus loin

Exécution parallèle multi-moteur de Bitroot : ordonnancement, sharding et surface de conflit Associés Vue d'ensemble de l'architecture EVM parallèle de Bitroot : comment consensus, exécution et état travaillent ensemble Associés Ce que signifie réellement la compatibilité EVM : bytecode, précompilations, JSON-RPC et outillage Prolongement sur la compatibilité
← PrécédentStorage Layout : comment les variables d'état Solidity atterrissent dans les slots
Sommaire
La frontière entre l'EVM et le reste du clientLes différences de positionnement des trois implémentationsLa cohérence ne se prouve pas par autotest : state test et tests multi-clientsLa distribution des instructions : table de saut, switch généré et inliningFacturation du gaz : séparation du constant et du dynamique, accès froids et chauds facturés au slotMémoire et cadres d'appel : sortir l'allocation du chemin chaudPrécompilés : implémentations natives et arbitrages de dépendancesPourquoi la compilation JIT n'est pas devenue le choix dominantDans quelles conditions ces optimisations ne portent pasSourcesPour aller plus loin
Réglages de lecture