7 points par GN⁺ 2025-12-24 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • MicroQuickJS(MQuickJS) est un moteur JavaScript ultra-léger conçu pour les systèmes embarqués, capable de fonctionner avec seulement environ 10 kB de RAM et 100 kB de ROM
  • Il adopte un ramasse-miettes par traçage et un stockage des chaînes en UTF-8 afin de réduire l’usage mémoire tout en conservant des performances proches de QuickJS
  • Le langage pris en charge est un sous-ensemble limité de JavaScript proche d’ES5, et seul le mode strict (strict mode) est autorisé afin d’interdire les syntaxes sujettes aux erreurs
  • L’outil REPL mqjs permet d’exécuter des scripts, d’enregistrer du bytecode et de définir des limites mémoire, et le bytecode généré peut être exécuté directement depuis la ROM
  • L’ensemble du moteur et de la bibliothèque standard réside en ROM, ce qui permet une initialisation rapide et une faible consommation mémoire, et améliore l’efficacité d’exécution de JavaScript en environnement embarqué

Introduction

  • MicroQuickJS(MQuickJS) est un moteur JavaScript destiné aux systèmes embarqués, fonctionnant avec 10 kB de RAM et 100 kB de ROM (code ARM Thumb-2 inclus)
    • Les performances sont proches de celles de QuickJS
  • Il ne prend en charge qu’un sous-ensemble proche d’ES5 et fonctionne uniquement en mode strict (strict mode), qui interdit les syntaxes inefficaces ou sujettes aux erreurs
  • Il partage une partie du code avec QuickJS, mais sa structure interne a été entièrement repensée pour économiser la mémoire
    • Utilisation d’un ramasse-miettes par traçage, de l’absence d’usage de la pile CPU et du stockage des chaînes en UTF-8

REPL

  • La commande REPL est mqjs et prend en charge l’exécution de scripts, l’évaluation, le mode interactif, la définition de limites mémoire et l’enregistrement du bytecode
    • Exemple : ./mqjs --memory-limit 10k tests/mandelbrot.js
  • L’option -o permet d’enregistrer le bytecode compilé dans un fichier
    • Le bytecode enregistré peut être exécuté avec ./mqjs mandelbrot.bin
  • Le bytecode diffère selon l’endianness du CPU et la taille des mots (32/64 bits), et l’option -m32 permet de générer du bytecode pour 32 bits
  • L’option --no-column permet de supprimer les numéros de colonne des informations de débogage

Mode strict

  • Seul le strict mode est autorisé ; l’usage du mot-clé with est impossible et les variables globales doivent impérativement être déclarées avec var
  • Les trous (holes) dans les tableaux ne sont pas autorisés
    • Exemple : a[10] = 2 provoque une TypeError
    • Si un tableau avec des trous est nécessaire, il faut utiliser un objet ordinaire
  • Seul l’eval global est pris en charge, sans accès aux variables locales
  • Le value boxing n’est pas pris en charge (new Number(1), etc.)

Sous-ensemble JavaScript

  • Basé sur le strict mode, avec une compatibilité principalement orientée ES5
  • L’objet Array ne contient pas de trous, et l’accès à un index hors limites provoque une erreur
  • for in ne parcourt que les propriétés propres de l’objet, et for of n’est pris en charge que pour les tableaux
  • L’objet global existe, mais sans getter/setter, et les propriétés créées directement n’apparaissent pas comme variables globales
  • Les expressions régulières (Regexp) ne gèrent la casse qu’en ASCII, et /./ correspond par point de code Unicode plutôt qu’en UTF-16
  • Les fonctions sur les chaînes ne traitent que l’ASCII (toLowerCase, toUpperCase)
  • Date ne prend en charge que Date.now()
  • Fonctions supplémentaires prises en charge :
    • for of, Typed arrays, littéraux de chaîne \u{hex}
    • Fonctions Math : imul, clz32, fround, trunc, log2, log10
    • Opérateur d’exponentiation, flags d’expressions régulières (s, y, u), fonctions sur les chaînes (replaceAll, trimStart, trimEnd), globalThis

API C

  • Dépendances minimales à la bibliothèque C, sans utilisation de malloc, free ni printf
  • Il faut fournir directement un tampon mémoire, et le moteur n’alloue de mémoire qu’à l’intérieur de ce tampon
    • Exemple : ctx = JS_NewContext(mem_buf, sizeof(mem_buf), &js_stdlib)
  • En raison du mode de fonctionnement du ramasse-miettes, il n’est pas nécessaire d’appeler JS_FreeValue()
  • L’adresse des objets pouvant changer à chaque allocation, il est recommandé d’utiliser des pointeurs JSValue
    • JS_PushGCRef() / JS_PopGCRef() permettent une gestion sûre des références
  • La bibliothèque standard est compilée en structures C pouvant être stockées en ROM, ce qui permet une initialisation rapide et une faible utilisation de la RAM
  • L’exécution du bytecode est possible depuis la ROM, après relocalisation avec JS_RelocateBytecode(), puis exécution via JS_LoadBytecode() et JS_Run()
  • Une bibliothèque mathématique (libm.c) et un émulateur de virgule flottante sont intégrés

Structure interne et comparaison avec QuickJS

  • Ramasse-miettes : utilisation d’un GC par traçage et compactage au lieu du comptage de références
    • Cela évite la fragmentation mémoire et réduit la taille des objets
  • Représentation des valeurs : conception adaptée à la taille des mots du CPU (32/64 bits)
    • Peut stocker des entiers sur 31 bits, des points de code Unicode, des flottants et des pointeurs vers des blocs mémoire
  • Les chaînes sont stockées en UTF-8, ce qui est plus efficace que l’approche en tableaux 8/16 bits de QuickJS
  • Les fonctions C peuvent être stockées comme une valeur unique, sans possibilité d’ajouter des propriétés
  • La bibliothèque standard réside en ROM, avec un minimum d’objets en RAM, ce qui permet une initialisation rapide du moteur
  • Le bytecode est basé sur une pile et traité en lecture seule via une table de références indirectes
    • Les numéros de ligne et de colonne sont compressés avec un code de Golomb
  • Le compilateur est similaire à celui de QuickJS, mais utilise un parseur non récursif pour limiter l’utilisation de la pile C
    • Génération du bytecode en un seul passage, sans arbre syntaxique

Tests et benchmarks

  • Test de base : make test
  • Micro-benchmarks QuickJS : make microbench
  • Le benchmark Octane (version modifiée pour le mode strict) peut être téléchargé séparément
    • Exécution : make octane

Licence

  • Distribué sous licence MIT
  • Le copyright du code source appartient à Fabrice Bellard et Charlie Gordon

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.