Membedah arsitektur inti WebAssembly: stack-based virtual machine, format binary .wasm vs teks .wat, model linear memory 32-bit, dan komponen-komponennya seperti functions, tables, globals, dan memories, plus cara embedding lewat JavaScript API

Setelah di episode 1 kita memahami mengapa WebAssembly lahir — performa near-native, sandbox, dan portabilitas — pada episode ini kita masuk ke dalam mesinnya: bagaimana arsitektur Wasm bekerja. Ini adalah fondasi paling penting sepanjang series, karena semua topik setelahnya — dari WAT syntax di episode 4 sampai optimasi di episode 15 — berdiri di atas pemahaman ini.
Mengapa arsitektur penting? Karena Wasm bukan bahasa pemrograman seperti JavaScript atau Rust. Ia adalah format bytecode yang dirancang untuk dieksekusi oleh mesin virtual. Memahami model eksekusinya akan menjelaskan mengapa ia cepat, mengapa ia aman, dan mengapa ada batasan-batasan tertentu yang tampak aneh bagi programmer aplikasi biasa.
Wasm adalah stack-based virtual machine. Artinya, hampir semua operasi bekerja dengan mengambil nilai dari tumpukan (stack), lalu menaruh hasilnya kembali ke tumpukan. Bandingkan dengan mesin berbasis register (seperti kebanyakan CPU x86/ARM) yang menyimpan nilai dalam register bernama.
Analoginya: bayangkan tumpukan piring. Untuk menghitung 2 + 3, kalian taruh angka 2 di atas tumpukan, taruh 3 di atasnya, lalu instruksi i32.add mengambil dua piring teratas dan menaruh hasilnya (5) sebagai satu piring baru.
Desain ini membuat format bytecode sangat ringkas dan mudah divalidasi — keuntungan besar untuk keamanan (setiap instruksi diverifikasi sebelum dieksekusi) dan untuk kompresi (ukuran file kecil).
.wasm dan Teks .watSebuah modul Wasm hadir dalam dua bentuk yang setara:
| Format | Ekstensi | Penjelasan |
|---|---|---|
| Binary | .wasm | Format yang benar-benar dieksekusi oleh engine — urutan byte ringkas |
| Textual | .wat | Representasi teks yang bisa dibaca manusia — seperti assembly untuk Wasm |
Keduanya bisa dikonversi bolak-balik. Tools seperti wat2wasm (dari wabt) dan wasm-tools mengubah .wat menjadi .wasm dan sebaliknya (wasm2wat). Semua modul Wasm diawali dengan magic number \0asm — empat byte 00 61 73 6d yang bisa kalian lihat langsung di hex editor.
wasm-tools parse hello.wat -o hello.wasm
xxd hello.wasm | head -1Baris pertama output xxd akan menampilkan 0000: 0061 736d — itulah magic number \0asm yang menandai sebuah modul Wasm valid.
Wasm memiliki model memory yang unik: linear memory. Bayangkan sebuah array raksasa byte (maksimum 4 GB karena address space 32-bit) yang bisa diakses dengan offset numerik. Tidak ada pointer seperti di C, tidak ada objek seperti di JS — hanya blok byte yang lurus.
memory.size menanyakan ukuran saat ini, memory.grow menambahkannya.ArrayBuffer (atau WebAssembly.Memory), sehingga bisa diakses sebagai Uint8Array/DataView.Dari sinilah datang batasan penting: Wasm murni tidak punya akses ke memory proses host kecuali lewat memory linear yang disediakan. Ini inti sandboxing — di episode 5 kita bedah memory secara mendalam.
Sebuah modul Wasm bisa berisi beberapa komponen. Empat yang paling penting:
Instruksi bekerja pada empat tipe numerik dasar: i32, i64 (integer), f32, f64 (floating point). Tidak ada tipe string, objek, atau boolean — semuanya direpresentasikan sebagai angka atau byte dalam memory.
Blok kode yang bisa dipanggil, dengan (param) dan (result). Fungsi export bisa dipanggil dari JavaScript; fungsi import disediakan oleh host (seperti console.log). Ini satu-satunya cara Wasm berinteraksi dengan dunia luar.
call_indirect). Detail di episode 5.Satu (atau lebih, dengan multi-memory di Wasm 3.0) area linear memory yang bisa diakses oleh instruksi load/store. Ukurannya dinamis via memory.grow, dan dari sisi JS direpresentasikan sebagai WebAssembly.Memory.
Wasm tidak pernah berjalan sendiri — ia selalu di-embed. Di browser, host-nya adalah JavaScript. Alur standarnya:
const { instance } = await WebAssembly.instantiateStreaming(
fetch("module.wasm"),
{ env: { hostFunction: () => console.log("dari host") } }
)
const hasil = instance.exports.fungsiYangDiexport(42)
console.log(hasil)WebAssembly.instantiate (atau versi streaming-nya) mengkompilasi bytecode sekaligus membuat instance — memori, tabel, dan fungsi yang siap dipanggil. Kita bedah seluruh API ini secara detail di episode 6.
Agar kalian tidak salah ekspektasi, catat batasan fundamental Wasm:
Tip
Visualkan modul Wasm sebagai mesin state terisolasi: ia menerima input angka, mengolahnya dalam memory linear-nya sendiri, dan mengembalikan output angka. Semua "dunia luar" diwakili lewat imports yang disediakan host.
Pada episode 2 ini, kalian telah memahami arsitektur inti WebAssembly sebagai stack-based virtual machine dengan linear memory 32-bit dan komponen modul yang terisolasi.
Inti yang harus dibawa pulang:
.wasm dan teks .wat, dimulai magic number \0asm.WebAssembly.instantiate.Di episode 3 selanjutnya, kita langsung praktik: instalasi dan Hello World pertama di WebAssembly — menulis modul .wat sederhana, mengkompilasinya menjadi .wasm dengan wasm-tools, dan menjalankannya di Node.js serta browser console. Sampai jumpa di episode 3!