- MicroQuickJS (MQuickJS) adalah engine JavaScript ultra-ringan yang dirancang untuk sistem embedded, dan dapat berjalan hanya dengan sekitar 10kB RAM dan 100kB ROM
- Untuk mempertahankan kecepatan yang mirip dengan QuickJS sambil mengurangi penggunaan memori, engine ini mengadopsi tracing garbage collector dan penyimpanan string UTF-8
- Bahasa yang didukung adalah subhimpunan JavaScript terbatas yang mendekati ES5, dan hanya mengizinkan strict mode yang melarang sintaks yang rawan kesalahan
- Melalui alat REPL
mqjs, pengguna dapat menjalankan skrip, menyimpan bytecode, dan menetapkan batas memori; bytecode yang dihasilkan juga dapat dijalankan langsung dari ROM
- Seluruh engine dan standard library tinggal di ROM untuk mewujudkan inisialisasi cepat dan konsumsi memori rendah, sehingga meningkatkan efisiensi eksekusi JavaScript di lingkungan embedded
Pengenalan
- MicroQuickJS (MQuickJS) adalah engine JavaScript yang menargetkan sistem embedded, dan berjalan dengan 10kB RAM serta 100kB ROM (termasuk kode ARM Thumb-2)
- Kecepatannya mirip dengan QuickJS
- Hanya mendukung subhimpunan yang mendekati ES5, dan hanya berjalan dalam strict mode yang melarang sintaks yang tidak efisien atau rawan kesalahan
- Meskipun berbagi sebagian kode dengan QuickJS, struktur internalnya dirancang sepenuhnya berbeda untuk menghemat memori
- Menggunakan tracing garbage collector, tanpa memakai stack CPU, dan penyimpanan string UTF-8
REPL
- Perintah REPL adalah
mqjs, dan mendukung eksekusi skrip, evaluasi, mode interaktif, pengaturan batas memori, serta penyimpanan bytecode
- Contoh:
./mqjs --memory-limit 10k tests/mandelbrot.js
- Dengan opsi
-o, bytecode hasil kompilasi dapat disimpan ke file
- Bytecode yang disimpan dapat dijalankan dengan
./mqjs mandelbrot.bin
- Bytecode berbeda tergantung endianness dan panjang word CPU (32/64-bit), dan opsi
-m32 dapat digunakan untuk membuat bytecode 32-bit
- Dengan opsi
--no-column, nomor kolom pada informasi debug dapat dihapus
Strict mode
- Hanya strict mode yang diizinkan; penggunaan kata kunci
with tidak didukung, dan variabel global wajib dideklarasikan dengan var
- Hole pada array tidak diizinkan
- Contoh:
a[10] = 2 akan menimbulkan TypeError
- Jika membutuhkan array dengan hole, gunakan objek biasa
- Hanya global eval yang didukung, tanpa akses ke variabel lokal
- Value boxing tidak didukung (
new Number(1) dan sejenisnya)
Subhimpunan JavaScript
- Berbasis strict mode, dengan fokus pada kompatibilitas ES5
- Objek Array tidak memiliki hole, dan akses indeks di luar rentang akan menghasilkan error
for in hanya mengiterasi properti milik objek itu sendiri, sedangkan for of hanya didukung untuk array
- Global object ada, tetapi getter/setter tidak didukung, dan properti yang dibuat langsung tidak diekspos sebagai variabel global
- Regular expression (Regexp) hanya membedakan huruf besar/kecil untuk ASCII, dan
/./ mencocokkan berdasarkan code point Unicode, bukan UTF-16
- Fungsi string hanya memproses ASCII (
toLowerCase, toUpperCase)
- Date hanya mendukung
Date.now()
- Fitur tambahan yang didukung:
for of, Typed arrays, literal string \u{hex}
- Fungsi Math:
imul, clz32, fround, trunc, log2, log10
- operator eksponen, flag Regexp (s, y, u), fungsi string (
replaceAll, trimStart, trimEnd), globalThis
C API
- Ketergantungan pada library C diminimalkan, tanpa penggunaan
malloc, free, atau printf
- Buffer memori harus disediakan secara langsung, dan engine hanya mengalokasikan memori di dalam buffer tersebut
- Contoh:
ctx = JS_NewContext(mem_buf, sizeof(mem_buf), &js_stdlib)
- Karena mekanisme garbage collection yang digunakan, pemanggilan
JS_FreeValue() tidak diperlukan
- Karena alamat objek dapat berpindah setiap kali alokasi, penggunaan pointer
JSValue direkomendasikan
JS_PushGCRef() / JS_PopGCRef() untuk manajemen referensi yang aman
- Standard library dikompilasi sebagai struktur C yang dapat disimpan di ROM, sehingga mencapai inisialisasi cepat dan penggunaan RAM rendah
- Eksekusi bytecode dapat dilakukan dari ROM, lalu direlokasi dengan
JS_RelocateBytecode() dan dijalankan dengan JS_LoadBytecode() serta JS_Run()
- Library matematika (
libm.c) dan emulator floating-point disertakan
Struktur internal dan perbandingan dengan QuickJS
- Garbage collection: menggunakan tracing GC terkompresi alih-alih reference counting
- Mencegah fragmentasi memori dan mengecilkan ukuran objek
- Representasi nilai: dirancang sesuai ukuran word CPU (32/64-bit)
- Dapat menyimpan integer 31-bit, code point Unicode, floating-point, dan pointer blok memori
- String disimpan dalam UTF-8, lebih efisien dibanding pendekatan array 8/16-bit milik QuickJS
- Fungsi C dapat disimpan sebagai nilai tunggal, tetapi tidak bisa ditambahi properti
- Standard library tinggal di ROM, dan objek RAM diminimalkan untuk memungkinkan inisialisasi engine yang cepat
- Bytecode berbasis stack, dan diperlakukan read-only melalui tabel referensi tidak langsung
- Nomor baris dan kolom dikompresi dengan kode Golomb
- Compiler mirip dengan QuickJS tetapi menggunakan parser non-rekursif untuk membatasi penggunaan stack C
- Menghasilkan bytecode dalam single pass tanpa parse tree
Pengujian dan benchmark
- Pengujian dasar:
make test
- Microbenchmark QuickJS:
make microbench
- Benchmark Octane (versi modifikasi untuk strict mode) dapat diunduh terpisah
Lisensi
- Didistribusikan di bawah lisensi MIT
- Hak cipta source code dimiliki oleh Fabrice Bellard dan Charlie Gordon
Belum ada komentar.