Geri Dön

PyWasm — Kapsamlı Teknik Dökümantasyon


Belgelenen sürüm: 2.2.3 Hedef spesifikasyon: WebAssembly Core Specification 2.0 (Taslak 2025-04-25) · WASI Preview 1 Python gereksinimi: ≥ 3.12 Lisans: MIT


İçindekiler

  1. Yönetici Özeti
  2. Projeye Genel Bakış
  3. Dizin Yapısı
  4. Mimari
  5. Bağımlılık Analizi
  6. Dosya Bazlı Dokümantasyon
  7. Çalıştırma Akışı
  8. API Dokümantasyonu
  9. Yapılandırma Dokümantasyonu
  10. Derleme ve Dağıtım
  11. Güvenlik Analizi
  12. Performans Analizi
  13. Geliştirici Kılavuzu
  14. İyileştirme Önerileri

1. Yönetici Özeti

pywasm, tamamen standart Python ile yazılmış eksiksiz bir WebAssembly yorumlayıcısıdır (üçüncü taraf kütüphane kullanılmaz). .wasm ikili dosyalarını çözümler, modülleri WebAssembly soyut makine semantiğine göre başlatır ve Python düzeyinde bir değerlendirme döngüsü içinde bayt kodunu talimat talimat çalıştırır.

Çözdüğü sorun

WebAssembly çalışma zamanları (Wasmtime, V8, Wasmer) hızlıdır; ancak yerel kod gerektirirler ve ikili yamalar olmadan saf-Python ortamlarına gömülmeleri ya da araçlanmaları zordur. pywasm, %100 taşınabilir, incelenebilir ve gömülebilir bir WebAssembly yorumlayıcısı nişini doldurur: CPython veya PyPy çalıştıran her yerde çalışır ve sıradan Python'da yazılmış host işlevlerle genişletilebilir.

Hedef kullanıcılar

Kitle Kullanım senaryosu
Araştırmacılar / güvenlik denetçileri WebAssembly çalıştırmasını izleme, her talimatı yakalama
Eğitimciler Okunabilir Python ile WebAssembly soyut makinesini inceleme
Araç geliştiriciler Yerel bağımlılıklar olmadan Wasm çalıştırmayı Python betiklerine gömme
CI/CD boru hatları Herhangi bir platformda Wasm modüllerini doğrulama

Temel özellikler

  • Tam WebAssembly 2.0 talimat seti (tamsayı, kayan nokta, SIMD, referans türleri, toplu bellek, tablo işlemleri)
  • WASI Preview 1 host uygulaması (dosya G/Ç, soketler, saatler, rastgelelik, ortam, sinyaller, yoklama)
  • Host işlev enjeksiyonu API'si — Wasm içinden Python çağrılabilirlerini çağırma
  • CLI giriş noktası (python -m pywasm)
  • Her kodu çözülen bölüm ve her çalıştırılan talimat için isteğe bağlı hata ayıklama düzeyinde izleme
  • PyPy uyumlu tasarım (PyPy üzerinde CPython'dan ≈10× hız artışı)
  • Kapsamlı spesifikasyon testi paketi ve WASI test paketi

Üst düzey mimari

┌─────────────────────────────────────────────────────────────┐
│                     Host / Kullanıcı                        │
│   pywasm.Runtime  ◄──► pywasm.wasi.Preview1                │
└─────────────────┬───────────────────────────────────────────┘
                  │  instance_from_file / invocate
┌─────────────────▼───────────────────────────────────────────┐
│                   pywasm.core.Machine                       │
│  ┌───────────┐  ┌────────────────────────────────────────┐  │
│  │   Store   │  │              Yığın (Stack)              │  │
│  │ func[]    │  │  value[] (ValInst)                     │  │
│  │ tabl[]    │  │  label[] (Label / kontrol akışı)       │  │
│  │ mems[]    │  │  frame[] (Frame / etkinleştirme kd.)   │  │
│  │ glob[]    │  └────────────────────────────────────────┘  │
│  │ elem[]    │                                              │
│  │ data[]    │  ← allocate() / instance() / invocate()      │
│  └───────────┘                                              │
└─────────────────┬───────────────────────────────────────────┘
                  │  bayt akışı
┌─────────────────▼───────────────────────────────────────────┐
│           pywasm.core.ModuleDesc (ikili çözümleyici)        │
│  Bölüm döngüsü: type / import / func / table / mem /       │
│                 global / export / start / elem / code / data│
└─────────────────────────────────────────────────────────────┘
         yardımcılar: pywasm.leb128 · pywasm.arith · pywasm.opcode

2. Projeye Genel Bakış

Proje hedefleri

  1. Önce doğruluk. Resmi WebAssembly spesifikasyon test paketini (çekirdek + SIMD) ve WASI preview-1 test paketini geçmek.
  2. Okunabilirlik. Her sınıf ve yöntem WebAssembly spesifikasyonunun düzyazısını yansıtır. Spesifikasyonu okuyan biri terminolojiyi doğrudan koda eşleyebilir.
  3. Gömülebilirlik. Genel API kasıtlı olarak küçük tutulmuştur: Runtime, instance_from_file, invocate, allocate_func_host.
  4. Sıfır bağımlılık. Yalnızca Python'un standart kütüphanesi (io, struct, ctypes, math, typing, platform, os, socket, …).

Temel kavramlar

Kavram Açıklama
ValType i32, i64, f32, f64, v128, ref.func, ref.extern'den biri
ValInst Herhangi bir WebAssembly değerini tutan 16 baytlık etiketli birleşim
ModuleDesc Bir .wasm ikilisinin statik, çözümlenmiş açıklaması (çalışma zamanı durumu yok)
ModuleInst Çalışma zamanı örneği: paylaşılan Store içine işaret eden dizin tabloları
Store İşlev, tablo, bellek, global, öğe ve veri örneklerinin paylaşılan heap'i
Machine Bir Store ve bir Stack'e sahiptir; değerlendirme döngüsünü yönetir
Label block / loop / if için kontrol akışı kaydı; geçerli talimat işaretçisini izler
Frame Bir işlev çağrısı için etkinleştirme kaydı; yerel değişkenleri ve modül bağlamını tutar
Runtime Machine etrafında kolaylık sarmalayıcısı; içe aktarma kaydını yönetir

Tasarım felsefesi

  • Spesifikasyona sadık adlandırma. Sınıflar, alanlar ve yöntemler mümkün olduğunca WebAssembly spesifikasyonunun söz dağarcığını kullanır (örn. ModuleInst, FuncInst, Store, allocate_func_wasm).
  • Her şey bir dizindir. ModuleInst, doğrudan referanslar değil Store listelerine tamsayı dizinleri saklar. Bu, modüller kararlı tutamaçlara sahipken store'un büyümesine olanak tanır.
  • 16 baytlık değer gösterimi. ValInst.data her zaman tam 16 baytlık bir bytearray'dir; ölçekli değerlerin yanı sıra v128'i (SIMD) tekdüze biçimde destekler. Ölçekli değerler düşük baytları kaplar; yüksek baytlar sıfırla doldurulur.
  • Yinelemeli değerlendirme döngüsü. Özyinelemeli işlev çağrıları yerine çalıştırma, stack.label üzerinde yinelemeli bir döngü kullanır. Frame ve Label girişleri çağrı ve kontrol akışı talimatları tarafından itilip çıkarılır. Bu Python'un çağrı yığınını sığ tutar ve tasarımı JIT dostu yapar.

Teknoloji yığını

Katman Teknoloji
Dil Python ≥ 3.12 (match/case, typing.Self kullanır)
İkili kodlama struct, özel LEB128 okuyucu
Aritmetik hassasiyet IEEE 754 için ctypes.c_float, struct.pack/unpack
WASI G/Ç os, fcntl, socket, select, stat, io (yalnızca Linux/macOS)
Wasm kaynak örnekleri Rust → wasm32-unknown-unknown / wasm32-wasip1
Test altyapısı Resmi WebAssembly spesifikasyon testleri, resmi WASI test paketi, WABT'dan wast2json
Paketleme hatchling (pyproject.toml)
CI GitHub Actions (macOS, Ubuntu, Windows, Python 3.14)

3. Dizin Yapısı

pywasm/                          ← depo kökü
├── .github/
│   └── workflows/
│       └── develop.yaml         ← CI: 3 İS × Python 3.14 üzerinde test
├── .gitignore
├── LICENSE                      ← MIT
├── MANIFEST.in                  ← sdist'e LICENSE dahil eder
├── README.md
├── pyproject.toml               ← hatchling derleme; sürüm 2.2.3
│
├── pywasm/                      ← KÜTÜPHANENİN KENDİSİ (Python paketi)
│   ├── __init__.py              ← yeniden dışa aktarmalar, sürüm, platform koruması
│   ├── __main__.py              ← CLI giriş noktası
│   ├── arith.py                 ← sabit genişlikli tamsayı ve IEEE 754 aritmetiği
│   ├── core.py                  ← 4193 satırlık yorumlayıcı kalbi
│   ├── leb128.py                ← LEB128 kodlama/çözme yardımcıları
│   ├── log.py                   ← hafif hata ayıklama kaydedici
│   ├── opcode.py                ← işlem kodu sabitleri + ad arama tablosu
│   └── wasi.py                  ← WASI Preview 1 uygulaması (Linux/macOS)
│
├── example/                     ← çalıştırılabilir Python sürücü betikleri
│   ├── blake2b.py               ← Wasm aracılığıyla Blake2b
│   ├── blake2b_direct.py
│   ├── blake2b_iter.py
│   ├── blake2b_simd.py
│   ├── fibonacci.py
│   ├── fibonacci_env.py         ← host işlev enjeksiyonu demosu
│   ├── pi.py
│   ├── wasi_httpbin.py
│   ├── wasi_ll.py
│   ├── wasi_stdout.py           ← stdout yakalama demosu
│   ├── wasi_zen.py
│   └── <isim>/                  ← her örnek için Rust crate'i
│       ├── Cargo.toml
│       ├── src/lib.rs  (veya main.rs)
│       └── bin/<isim>.wasm      ← önceden derlenmiş ikili (depoya eklendi)
│
├── res/
│   └── pywasm.jpg               ← proje logosu
│
├── script/
│   ├── build_example.py         ← tüm Rust örneklerini → .wasm olarak derler
│   ├── build_spec.py            ← spec test paketini klonlar/günceller, wast2json çalıştırır
│   ├── build_wabt.py            ← platforma uygun WABT sürümünü indirir
│   └── build_wasi.py            ← wasi-testsuite'i indirir
│
└── test/
    ├── example.py               ← tüm example/ betiklerini çalıştırır
    ├── main.py                  ← CLI duman testi (pi, wasi_ll)
    ├── spec.py                  ← WebAssembly spesifikasyon uyumluluk test koşucusu
    └── wasi.py                  ← WASI test koşucusu

Dizin rolleri

Dizin Rol
pywasm/ Dağıtılabilir Python paketi. Bir son kullanıcının kurduğu her şey.
example/ Tüm genel API yüzeylerini gösterir; Rust kaynağı gerçeğin kaynağıdır; .wasm ikilileri depoya eklenmiştir, böylece depo Rust araç zinciri olmadan kullanılabilir.
script/ Yalnızca geliştirici otomasyonu: araçları indirir, örnekleri derler, test armatürlerini hazırlar. sdist'e dahil edilmez.
test/ Test paketi. script/ tarafından oluşturulan harici armatürler gerektirir.
res/ Statik varlıklar (logo).
.github/ CI yapılandırması.

4. Mimari

4.1 Sistem mimarisi

pywasm, tek süreçli, tek iş parçacıklı bir yorumlayıcıdır. Çalışma zamanında ağ çağrıları, arka plan iş parçacıkları veya yabancı işlev arabirimleri yoktur. Geliştirme zamanında yalnızca harici süreçler oluşturulur (betikler tarafından) — cargo build, wast2json, git.

4.2 Bileşen mimarisi

┌──────────────────────────────────────────────────┐
│              Genel API Katmanı                   │
│   Runtime (core.py)                              │
│   ├── allocate_func_host()                       │
│   ├── allocate_table()                           │
│   ├── allocate_memory()                          │
│   ├── allocate_global()                          │
│   ├── instance() / instance_from_file()          │
│   ├── invocate()                                 │
│   ├── exported_memory()                          │
│   └── exported_global()                          │
└──────────────────┬───────────────────────────────┘
                   │
┌──────────────────▼───────────────────────────────┐
│               Machine (core.py)                  │
│  ├── Store ─► FuncInst | FuncHost                │
│  │            TableInst                          │
│  │            MemInst (bytearray, sayfalar)      │
│  │            GlobalInst                         │
│  │            ElemInst                           │
│  │            DataInst                           │
│  ├── Stack ─► value: list[ValInst]               │
│  │            label: list[Label]                 │
│  │            frame: list[Frame]                 │
│  │                                               │
│  ├── allocate()   — Store'u doldurur, ModInst d. │
│  ├── instance()   — içe aktarmaları doğrular     │
│  ├── invocate()   — genel işlev çağrı girişi     │
│  └── evaluate()   — bayt kodu gönderim döngüsü  │
└──────────────────┬───────────────────────────────┘
                   │
┌──────────────────▼───────────────────────────────┐
│          İkili Çözümleyici (core.py)             │
│   ModuleDesc.from_reader()                       │
│   ├── Bölüm 0x01 — type   (FuncType)            │
│   ├── Bölüm 0x02 — import (Import)              │
│   ├── Bölüm 0x03 — func   (FuncDesc tür ref)    │
│   ├── Bölüm 0x04 — table  (TableType)           │
│   ├── Bölüm 0x05 — memory (MemType)             │
│   ├── Bölüm 0x06 — global (GlobalDesc+Expr)     │
│   ├── Bölüm 0x07 — export (ExportDesc)          │
│   ├── Bölüm 0x08 — start  (işlev dizini)        │
│   ├── Bölüm 0x09 — elem   (ElemDesc)            │
│   ├── Bölüm 0x0a — code   (LocalsDesc+Expr)     │
│   ├── Bölüm 0x0b — data   (DataDesc)            │
│   └── Bölüm 0x0c — datacount                    │
└──────────────────────────────────────────────────┘
         ↑ kullanır
┌─────────────────────────────────────────────────┐
│          Destek Modülleri                       │
│   leb128.py  — işaretsiz/işaretli LEB128 G/Ç   │
│   arith.py   — sabit genişlikli aritmetik yrd. │
│   opcode.py  — işlem kodu sabitleri + ad tab.  │
│   log.py     — zaman damgalı hata ayıklama çık.│
└─────────────────────────────────────────────────┘

4.3 Çalışma zamanı mimarisi (soyut makine)

WebAssembly spesifikasyonu çalıştırmayı bir Store ve bir Stack açısından tanımlar. pywasm her ikisini de sadakatle uygular.

Store

Tüm çalışma zamanı nesneleri Machine başına tek bir Store'da yaşar:

Store.func  : list[FuncInst | FuncHost]   # işlev örnekleri
Store.tabl  : list[TableInst]             # tablo örnekleri
Store.mems  : list[MemInst]              # doğrusal bellek örnekleri
Store.glob  : list[GlobalInst]           # global değişken örnekleri
Store.elem  : list[ElemInst]             # öğe segmenti örnekleri
Store.data  : list[DataInst]             # veri segmenti örnekleri

Bu listelerdeki dizinler adresler olarak hizmet eder. Bir ModuleInst, her kategori için modül-yerel dizinleri store adreslerine eşleyen list[int] tutar.

Stack

Stack.value : list[ValInst]    # operand yığını
Stack.label : list[Label]      # kontrol akışı yığını
Stack.frame : list[Frame]      # çağrı çerçevesi yığını

Üçü de Python listesidir ve yığın olarak kullanılır (append / pop). Spesifikasyon üç türü de kavramsal tek bir yığında karıştırır; pywasm bunları çerçeve/etiket derinliğine göre dizinlenen üç paralel listeye ayırır.

Label

class Label:
    arity : int        # dönüş değerlerinin sayısı
    frame : int        # etiket girişindeki çerçeve derinliği
    value : int        # etiket girişindeki değer-yığını derinliği
    carry : int        # 0x00 = döngüye geri dön, 0x01 = etiketi çıkar, 0x03 = çerçeveyi de çıkar
    instr : list[Inst] # çalıştırılacak talimat dizisi
    index : int        # instr içindeki geçerli talimat işaretçisi

carry bir bit alanıdır. Bit 0 dal semantiğini kontrol eder (döngü vs blok). Bit 1 etiketin bir Frame ile ilişkilendirildiğini gösterir (yani bir işlev etkinleştirmesi), bu nedenle etiketi çıkarmak çerçeveyi de çıkarır.

Frame

class Frame:
    module : ModuleInst    # dizinleri çözümlemek için modül bağlamı
    locals : LocalsInst    # yerel değişkenler (bağımsız değişkenler dahil)
    arity  : int           # beklenen dönüş değerlerinin sayısı
    label  : int           # çerçeve girişindeki etiket-yığını derinliği
    value  : int           # çerçeve girişindeki değer-yığını derinliği

4.4 İşlem kodu gönderimi

Machine.evaluate() yöntemi sıkı bir yinelemeli döngüdür:

for _ in range(1 << 32):     # pratikte sonsuz; istisna çıkar
    label = self.stack.label[-1]
    frame = self.stack.frame[-1]
    if label.index == len(label.instr):
        self.stack.label.pop()
        if label.carry & 2:  # çerçeve taşıyan etiket
            self.stack.frame.pop()
        continue
    instr = label.instr[label.index]
    label.index += 1
    match instr.opcode:
        case opcode.i32_add: ...
        case opcode.call:    ...
        # ... 400+ durum

Her yineleme:

  1. Geçerli etiketi (etiket yığınının üstü) alır
  2. Talimat listesi tükenirse etiketi çıkarır (ve isteğe bağlı olarak çerçeveyi)
  3. Aksi takdirde sonraki talimatı alır ve match aracılığıyla gönderir

Bu tasarım çoğu aritmetik talimat için yineleme başına tahsisattan bağımsızdır (yalnızca liste dizinleme ve ValInst oluşturma).

4.5 Kontrol akışı mekaniği

Talimat Efekt
block Bloğun talimat listesiyle yeni bir Label(carry=1) iter
loop Yeni bir Label(carry=0) iter — br, index'i 0'a sıfırlar (döngüye geri döner)
if Koşulu çıkarır; ya then ya da else talimat listesiyle Label iter
br n evaluate_br(n): n etiketi etiket yığınından çıkarır, arity değerlerini toplar, değer yığınını geri yükler
br_if Koşullu br
br_table Dizinli br
return Çerçeve etiketine kadar ve dahil olmak üzere tüm etiketleri çıkarır
call Yeni bir Frame ve çağrılanın talimat listesini içeren yeni bir Label(carry=3) iter

4.6 Başlatma yaşam döngüsü

Kullanıcı → Runtime.instance_from_file(yol)
  → open(yol) → ModuleDesc.from_reader()
  → Machine.instance(modül, extern_listesi)
    → içe aktarmaları doğrula
    → yardımcı Frame it
    → global başlatma ifadelerini değerlendir
    → öğe başlatma ifadelerini değerlendir
    → allocate(modül, extern, globin, elemin)
      → ModuleInst döndürür
    → newmod Frame it
    → aktif öğe segmentlerini çalıştır (table_init)
    → aktif veri segmentlerini çalıştır (memory_init)
    → başlangıç işlevini çağır (varsa)
    → newmod Frame'i çıkar
    → ModuleInst döndür
  → Kullanıcıya ModuleInst döndür

4.7 WASI entegrasyon mimarisi

┌──────────────────────┐
│  Preview1 (wasi.py)  │   bind(runtime)  →  "wasi_snapshot_preview1" altında
│                      │                     45 host işlev kaydeder
│  fd: list[File]      │
│  args, dirs, envs    │
│  return_on_exit      │
└──────────┬───────────┘
           │  call_indirect/call aracılığıyla Wasm'dan çağrılan host işlevleri
           ▼
┌──────────────────────┐
│  Machine (evaluate)  │   FuncHost.hostcode(machine, args) → rets
│                      │
│  iovec, stat yapıları│
│  vb. için doğrusal   │
│  belleği okur/yazar  │
└──────────────────────┘
           │
           ▼
   İS: open/read/write/socket/...

WASI işlevleri bir Machine referansı ve zaten paketinden çıkarılmış bağımsız değişken değerlerinin list[int]'ini alır. Doğrusal belleğe machine.store.mems[...].get_u32(ptr) vb. aracılığıyla erişirler. Sonuçlar belleğe geri yazılır ve bir hata kodu list[int] olarak döndürülür.


5. Bağımlılık Analizi

pywasm'ın Python standart kütüphanesi dışında sıfır çalışma zamanı bağımlılığı vardır.

Modül Kullanan Amaç
ctypes arith.py, core.py IEEE 754 tek hassasiyetli yuvarlama için c_float; bayt düzeni için struct
struct arith.py, core.py Little-endian tamsayıları ve kayan noktaları paketleme/paket açma
math arith.py, core.py Kayan nokta talimatları için isnan, isinf, copysign, ceil, floor, trunc, sqrt
io leb128.py, core.py Bölüm düzeyinde ayrıştırma için aranabilir bayt okuyucu olarak io.BytesIO
typing core.py, leb128.py Tür ipuçları için typing.Self, typing.Any, typing.Callable
platform __init__.py, wasi.py wasi'yi koşullu olarak içe aktarmak için İS algılama
os wasi.py Tüm POSIX dosya işlemleri
fcntl wasi.py Engellemesiz / ekleme bayrağı değişiklikleri için fcntl.F_SETFL
socket wasi.py sock_accept, sock_recv, sock_send, sock_shutdown için TCP/UDP soket işlemleri
select wasi.py poll_oneoff abonelik yoklaması için select.select()
stat wasi.py WASI dosya türü eşlemesi için stat.S_ISREG, stat.S_ISDIR
random wasi.py random_get için random.randbytes()
time wasi.py WASI saatleri için time.time_ns(), time.monotonic_ns(), time.process_time_ns()
dataclasses wasi.py Preview1.File tanımlayıcısı için @dataclasses.dataclass
sys wasi.py, __main__.py sys.stdin/stdout/stderr dosya tanımlayıcıları; sys.exit()
argparse __main__.py CLI bağımsız değişken ayrıştırma

Derleme zamanı (yalnızca geliştirici)

Araç Amaç
hatchling PEP 517 derleme arka ucu (pyproject.toml'de bildirilmiş)
wabt (wast2json) .wast spesifikasyon testlerini .json + .wasm'a dönüştürür
Rust + cargo Örnek Wasm ikilileri derler (wasm32-unknown-unknown, wasm32-wasip1)
git Resmi WebAssembly spesifikasyonunu ve WASI test paketi depolarını klonlar

6. Dosya Bazlı Dokümantasyon

6.1 pywasm/__init__.py

Dosya amacı

Paket giriş noktası. core'un genel yüzeyini yeniden dışa aktarır, wasi'yi koşullu olarak içe aktarır (yalnızca POSIX) ve kütüphane sürümünü bildirir.

Temel bileşenler

version = '2.2.3'

Sürüm dizisi pyproject.toml'de kopyalanmıştır. İkisi arasında otomatik senkronizasyon yoktur.

Platform koruması

if platform.system().lower() in ['darwin', 'linux']:
    from . import wasi

wasi.py, Windows'ta mevcut olmayan fcntl, select, os.pread ve POSIX'e özgü dir_fd= bağımsız değişkenlerini kullanır. Koruma, Windows'ta ImportError'ı önler; burada WASI programları şu anda pywasm aracılığıyla çalıştırılamaz.

İlişkiler

  • Şunlardan içe aktarır: arith, core, leb128, log, opcode, koşullu olarak wasi
  • from .core import *, core.py'deki tüm genel sembolleri pywasm ad alanı düzeyinde kullanılabilir kılar

6.2 pywasm/log.py

Dosya amacı

Yorumlayıcı boyunca hata ayıklama izlemesi için kullanılan minimal zaman damgalı kaydedici.

Temel bileşenler

lvl = 0  # global hata ayıklama düzeyi; izlemeyi etkinleştirmek için 1 olarak ayarla

def debugln(*args):
    if lvl > 0:
        println(*args)

def println(*args):
    pre = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
    print(pre, 'pywasm:', *args)

İç mantık

debugln, lvl tarafından korunur. pywasm.log.lvl = 1 ayarı şunları içeren ayrıntılı çıktıyı etkinleştirir:

  • İkili çözümlenirken her bölüm başlığı
  • evaluate() sırasında çalıştırılan her talimat
  • Global ve öğe başlatıcı değerlendirmeleri

Notlar

  • 1'in üzerinde bir günlük düzeyi yoktur (herhangi bir sıfırdan farklı değer hata ayıklama çıktısını etkinleştirir).
  • Dosya tabanlı günlük kaydı veya yapılandırılmış günlük kaydı yoktur. Tüm çıktı stdout'a gider.
  • İzlemeyi etkinleştirmek, her talimat için dize biçimlendirmesi gerçekleştiğinden önemli ek yük oluşturur.

6.3 pywasm/leb128.py

Dosya amacı

WebAssembly ikili biçimi tarafından belirtilen LEB128 (Little-Endian Base-128) değişken uzunluklu tamsayı kodlamasının uygulaması.

Temel bileşenler

class _U — İşaretsiz LEB128
Yöntem İmza Açıklama
encode (i: int) → bytearray Negatif olmayan bir tamsayıyı kodlar
decode (b: bytearray) → int Önceden okunan bir bytearray'i çözer
decode_reader (r: io.IOBase) → tuple[int, int] MSB 0 olana kadar bir akıştan bayt okur; (değer, okunan_bayt) döndürür
class _I — İşaretli LEB128

_U ile aynı arabirim, ancak decode'da iki tümleyenli işaret genişletmesini işler:

if e & 0x40 != 0:               # son baytın işaret biti ayarlandıysa
    r |= - (1 << (i * 7) + 7)  # işaret genişletme
Modül düzeyinde tekil nesneler
u = _U()   # işaretsiz LEB128 kod çözücüsü
i = _I()   # işaretli LEB128 kod çözücüsü

Bunlar core.py boyunca pywasm.leb128.u.decode_reader(r) olarak kullanılır.

İç mantık

Kodlama döngüsü, devam bayrağı olarak yüksek bit (0x80) ayarlanmış şekilde bayt başına 7 bit biriktirir. Çözücü bunu tersine çevirir ve devam bayrağı olmayan birine kadar bayt toplar.

Notlar

  • decode_reader, (değer, okunan_bayt_sayısı) demeti döndürür, ancak neredeyse tüm çağrı sitelerinde yalnızca [0] (değer) kullanılır.
  • Maksimum bayt uzunluğu doğrulaması yoktur. Sonsuz devam-bit akışına sahip hatalı biçimlendirilmiş girdiler sonsuza kadar döner.

6.4 pywasm/arith.py

Dosya amacı

Python'un keyfi hassasiyetli varsayılanlarından farklı olan WebAssembly tamsayı ve kayan nokta semantiğini doğru biçimde uygulayan sabit genişlikli aritmetik yardımcı sınıfları.

Temel bileşenler

class I(blen)blen baytlık işaretli tamsayı
Öznitelik Değer (I(4) için)
bits_length 32
byte_length 4
mask 0xFFFFFFFF
mask_sign 0x80000000
max 2147483647
min -2147483648

Temel yöntemler:

  • fit(n)n'yi iki tümleyenli maskeleme kullanarak işaretli aralığa sarar:
    n = n & self.mask                        # bit genişliğine kes
    n = n - ((n & self.mask_sign) << 1)     # işaret genişletme
    
  • div(a, b)Sıfıra doğru kesmeli bölme uygular (WebAssembly gereksinimi):
    return a // b if a * b > 0 else (a + (-a % b)) // b
    
    Python'un yerel //'si negatif sonsuza doğru keser; bu düzeltme doğruluk açısından kritiktir.
  • rem(a, b) — Eşleşen işaretli kalan (her zaman bölünenin işaretine sahiptir).
  • shl/shr — Kaydırma miktarı bits_length - 1 ile maskelenir (WebAssembly gereksinimi).
class U(blen) — İşaretsiz tamsayı

Aynı yapı ancak fit yalnızca n & mask'tir. Döndürme ve bit sayma işlemleri ekler:

  • rotl(a, b) / rotr(a, b) — Dairesel bit döndürme
  • clz(a) — Baştaki sıfırları say (bit döngüsü, O(bits_length))
  • ctz(a) — Sondaki sıfırları say
  • popcnt(a) — Popülasyon sayımı (ayarlı bitleri say)
class F32 ve class F64 — IEEE 754 kayan nokta sarmalayıcıları
  • F32.fit(n), 32 bit hassasiyete yuvarlamak için ctypes.c_float(n).value kullanır — Python'un float'ı her zaman 64 bit olduğundan doğruluk açısından önemlidir.
  • F64.div(a, b), WebAssembly'ye göre sıfıra bölmeyi işler: doğru işaretle ±∞ veya NaN döndürür.
  • min/max — Her iki operanddaki NaN'yi yayar (WebAssembly NaN yayma kuralları Python'un min/max'inden farklıdır).
Modül düzeyinde tekil nesneler
i8, u8, i16, u16, i32, i64, u32, u64 = I(1), U(1), I(2), U(2), I(4), I(8), U(4), U(8)
f32, f64 = F32(), F64()

Bunlar core.py tarafından pywasm.arith.i32.add(a, b) vb. olarak içe aktarılır.

Notlar

  • clz, ctz, popcnt O(N) bit-bit döngülerdir. N=64 (i64) için bu 64 yinelemedir — bir yorumlayıcı için kabul edilebilir ancak optimal değil. int.bit_count() (Python 3.10+) popcnt'nin yerini alabilir.
  • I.div özel durumu: assert a != self.min or b != -1, INT_MIN / -1 üzerindeki tamsayı taşmasına karşı koruma sağlar.

6.5 pywasm/opcode.py

Dosya amacı

İşlem kodu sabitleri ve hata ayıklama ekranı için bir name sözlüğü içeren düz modül. SIMD (0xfd öneki), doyurucu kesme (0xfc öneki) ve referans türleri dahil olmak üzere 2.0 spesifikasyonundaki her WebAssembly işlem kodunu içerir.

Temel bileşenler

# Temel işlem kodları (tek bayt)
unreachable = 0x00
nop         = 0x01
block       = 0x02
...
# Genişletilmiş işlem kodları (0xfc önekli iki bayt, birleşik int olarak kodlanmış)
i32_trunc_sat_f32_s = 0xfc00
memory_init         = 0xfc08
...
# SIMD işlem kodları (0xfd öneki)
v128_load   = 0xfd00
i8x16_shuffle = 0xfd0d
...

Notlar

  • Modül 437 işlem kodu tanımı ve 437 karşılık gelen name girişi içerir.
  • Tamamen bildirimseldir — mantık yok, içe aktarma yok. Bu, içe aktarmayı çok ucuz yapar.

6.6 pywasm/core.py

Dosya amacı

4193 satırlık merkezi modül. Şunları içerir:

  • Tüm tür-tanımlayıcı ve çalışma zamanı-örneği sınıfları (WebAssembly spesifikasyonunu yansıtır)
  • İkili modül çözümleyici (ModuleDesc.from_reader)
  • Soyut makine (Machine)
  • Genel kolaylık API'si (Runtime)

6.6.1 Değer sistemi

class ValType

Tek bayt olarak kodlanmış yedi WebAssembly değer türü:

Sabit Değer Anlam
0x7f i32 32 bitlik tamsayı
0x7e i64 64 bitlik tamsayı
0x7d f32 32 bitlik kayan nokta
0x7c f64 64 bitlik kayan nokta
0x7b v128 128 bitlik SIMD vektörü
0x70 ref.func İşlev referansı
0x6f ref.extern Harici referans

Fabrika sınıf yöntemleri: ValType.i32(), ValType.f32(), vb.

class ValInst

16 baytlık etiketli değer. data alanı her zaman tam 16 bayttır.

i32 değeri 42 için düzen:
  bayt  0-3:  little-endian 42 (0x2a 0x00 0x00 0x00)
  bayt  4-15: sıfırlar

ref (işlev dizini 7, null değil) için düzen:
  bayt  0-3:  işaretli 32 bit little-endian 7
  bayt  4:    0x01 (null-olmayan bayrağı)
  bayt  5-15: sıfırlar

v128 için düzen:
  bayt  0-15: vektörün ham 16 baytı

Oluşturma yöntemleri (sınıf yöntemleri): from_i32, from_i64, from_u32, from_u64, from_f32, from_f64, from_v128, from_v128_i8from_v128_f64, from_ref, from_all.

Çıkarma yöntemleri (örnek yöntemleri): into_i32, into_i64, into_u32, into_u64, into_f32, into_f64, into_v128, into_v128_i8into_v128_f64, into_ref, into_all.

6.6.2 Tür tanımlayıcılar (statik / ikili dosyadan çözümlenmiş)

Sınıf Amaç
Bype Blok türü — boş (0x40), tek değer türü veya işlev türü dizini
Inst Tek çözümlenmiş talimat: opcode + args listesi
Expr end ile sonlandırılan Inst listesi
LocalsDesc Yerel değişken bildirimi için n × tür çifti
LocalsInst ValInst yerellerinin çalışma zamanı değiştirilebilir listesi
FuncType args: list[ValType], rets: list[ValType]
FuncDesc Tür dizini + yereller + gövde Expr
Limits n (min), m (max, 0 = sınırsız)
MemType Limits'i sarar
TableType ValType + Limits
GlobalType ValType + değiştirilebilirlik bayrağı (0=sabit, 1=değiştirilebilir)
GlobalDesc GlobalType + başlatıcı Expr
Import Modül adı, öğe adı, tür, tanımlayıcı
Extern Çalışma zamanı harici değer: tür + store adresi
ExportDesc Ad, tür (func/table/mem/global), tanımlayıcı dizini
ElemDesc Öğe segmenti (spesifikasyona göre 8 tür)
DataDesc Veri segmenti (spesifikasyona göre 3 tür)
Custom Özel bölüm (semantikler tarafından göz ardı edilir)
ModuleDesc Tüm çözümlenmiş bölümler toplulaştırılmış

6.6.3 Inst.from_reader — talimat çözümleyici

Bir BytesIO okuyucudan bir kerede bir talimat okuyan yaklaşık 350 satırlık bir match ifadesi. Yapılandırılmış kontrol talimatları için (block, loop, if) end'e kadar (veya if için else) özyinelemeli olarak okur ve iç içe talimat listelerinden oluşan bir ağaç oluşturur.

Bellek talimatları için hizalama+ofset anlık çiftlerini okur ve hizalamanın spesifikasyon sınırları içinde olduğunu doğrular.

f32/f64 sabit kodlama notu:

case opcode.f32_const:
    # Python, float'a dönüştürüldüğünde 0x7fa00000'i 0x7fe00000 olarak yanlış yorumlar.
    o.args.append(struct.unpack('<i', r.read(4))[0])  # ham int olarak sakla

Kayan nokta sabitleri Python'un NaN kanonizasyonundan kaçınmak için ham bit örüntüleri (işaretli int32/int64) olarak saklanır. Çalıştırma zamanında ValInst.from_f32_u32 aracılığıyla yeniden yorumlanırlar.

6.6.4 ModuleDesc.from_reader — ikili modül çözümleyici

Wasm ikili biçimini okur:

  1. Sihirli \x00asm ve sürüm \x01\x00\x00\x00'ı kontrol eder
  2. Her birini BytesIO alt okuyucusu olarak okuyarak 32 bölüme kadar döngü yapar
  3. Bölüm ID'sine göre gönderir (0–12)
  4. Kod bölümü (0x0a) özeldir: her biri kendi LEB128 uzunluğu ile boyutlandırılmış işlev gövdelerinin sayısıdır

6.6.5 Çalışma zamanı örnekleri

Sınıf Açıklama
ModuleInst Modül başına dizin tabloları (type, func, tabl, mems, glob, elem, data, exps)
FuncInst Wasm tanımlı işlev: tür, modül bağlamı, kod
FuncHost Python tarafından barındırılan işlev: tür, çağrılabilir
MemInst Doğrusal bellek: bytearray verisi + sayfa sayısı; grow(n) 64KiB sayfaları ekler
TableInst Tablo: referansların list[ValInst]'i; grow(n, v) v değerinin n kopyasını ekler
GlobalInst Global: data: ValInst + değiştirilebilirlik bayrağı
ElemInst Öğe segmenti: tür + list[ValInst] referansları
DataInst Veri segmenti: bytearray

MemInst bellek sınırları: memory_grow talimatı ayrıca 1024 sayfaya (64 MiB) sabitlenmiştir:

cnda = size + incr <= 1024   # sabit üst sınır
cndb = mems.type.limits.m == 0 or size + incr <= mems.type.limits.m

Bu, spesifikasyon gereksinimi değil, kasıtlı bir yerleştirici politikasıdır.

6.6.6 Machine.allocate — kaynak tahsisi

ModuleDescModuleInst'i kaynak tahsis ederek eşler:

  1. Harici değerler (içe aktarmalardan) modül dizin tablolarına eklenir
  2. store.allocate_func_wasm(inst, func)FuncInst oluşturur, store adresi döndürür
  3. store.allocate_table, allocate_memory, allocate_global, allocate_elem, allocate_data benzer şekilde
  4. Dışa aktarma tanımlayıcıları ExportInst girişlerine çözümlenir

6.6.7 Machine.instance — modül başlatma

Tam spesifikasyon tanımlı başlatma prosedürü:

  1. İçe aktarma listesi uzunluğunun ve türlerinin bildirilmiş içe aktarmalarla eşleştiğini doğrula
  2. Her içe aktarmayı bildirilmiş tanımlayıcıya karşı tür kontrol et
  3. Global/öğe başlatma ifadelerinin çalışmasına izin vermek için yardımcı Frame it
  4. Her global başlatıcı ifadesini değerlendir
  5. Her öğe başlatıcı ifadesini değerlendir
  6. Gerçek ModuleInst'i oluşturmak için allocate() çağır
  7. Gerçek modülle çerçeveyi yeniden it
  8. Aktif öğe segmentlerini çalıştır (table_init + elem_drop)
  9. Bildirimsel öğe segmentlerini çalıştır (elem_drop)
  10. Aktif veri segmentlerini çalıştır (memory_init + data_drop)
  11. Bildirilmişse başlangıç işlevini çağır
  12. Çerçeveyi çıkar ve ModuleInst döndür

6.6.8 Machine.invocate — işlev çağrısı

Dışa aktarılan bir işlevi çağırmak için genel giriş noktası:

  1. Bağımsız değişken türlerini doğrula
  2. Sentinel Frame it (aşırı açmayı algılamak için)
  3. Bağımsız değişkenlerden + sıfır başlatılmış yerel değişkenlerden yerelleri oluştur
  4. Gerçek Frame'i ve işlev gövdesini içeren başlangıç Label(carry=3)'ü it
  5. evaluate() çağır
  6. Değer yığınından dönüş değerlerini çıkar
  7. Dönüş türlerini doğrula
  8. Sentinel çerçeveyi çıkar; yığınların boş olduğunu doğrula

6.6.9 Machine.evaluate — gönderim döngüsü

Yorumlayıcının kalbi. Bir for döngüsü içinde yaklaşık 2300 satırlık tek bir match instr.opcode: ifadesi. Dikkat çekici uygulama kalıpları:

Bellek talimatları:

def evaluate_mem_load(self, offset: int, size: int) -> bytearray:
    mems = self.store.mems[self.stack.frame[-1].module.mems[0]]
    addr = self.stack.value.pop().into_u32() + offset
    assert addr + size <= len(mems.data)    # sınır dışında tuzak
    return mems.data[addr:addr+size]

Dal işleme (evaluate_br):

def evaluate_br(self, l: int) -> None:
    label = self.stack.label[-1 - l]       # hedef etiket (derinlik l)
    rets = [self.stack.value.pop() for _ in range(label.arity)][::-1]
    self.stack.frame = self.stack.frame[:label.frame]  # çerçeveleri aç
    self.stack.label = self.stack.label[:len(self.stack.label)-l]
    match label.carry & 1:
        case 0x00: label.index = 0    # döngü: başa sıfırla
        case 0x01: self.stack.label.pop()  # blok: etiketten çık
    self.stack.value = self.stack.value[:label.value]
    self.stack.value.extend(rets)

SIMD talimatları — hepsi aynı kalıbı izler: v128 operandlarını yazılı listeler olarak çıkar, öğe bazında işlem uygula, sonucu it:

case opcode.i8x16_add:
    b = self.stack.value.pop().into_v128_i8()
    a = self.stack.value.pop().into_v128_i8()
    c = [pywasm.arith.i8.add(a[i], b[i]) for i in range(16)]
    self.stack.value.append(ValInst.from_v128_i8(c))

6.6.10 class Runtime

Genel API cephesi. Bir Machine ve bir imports sözlüğüne sahiptir:

class Runtime:
    machine: Machine
    imports: dict[str, dict[str, Extern]]   # modül_adı → {öğe_adı → Extern}
Yöntem Açıklama
allocate_func_host(type, func) Python çağrılabilirini host işlev olarak kaydet
allocate_table(type) İçe aktarma için tablo önceden tahsis et
allocate_memory(type) İçe aktarma için bellek önceden tahsis et
allocate_global(type, data) İçe aktarma için global önceden tahsis et
exported_memory(module, name) Dışa aktarılan MemInst'i ara
exported_global(module, name) Dışa aktarılan GlobalInst'i ara
instance(module) ModuleDesc'ten başlat; içe aktarmaları self.imports'tan çöz
instance_from_file(path) Dosya aç → ModuleDesc.from_readerinstance()
invocate(module, func, args) Dışa aktarılan işlevi ada göre çağır; Python değerlerini ValInst'e otomatik dönüştür

Host işlev çağrı kuralı:

# Tüm host işlevleri için gerekli imza:
def my_func(machine: pywasm.core.Machine, args: list[int|float|...]) -> list[int|float|...]:
    ...

Machine referansı, host işlevlerine bellek, globaller ve çağrı yığınına tam erişim sağlar.


6.7 pywasm/__main__.py

Dosya amacı

python -m pywasm olarak çağrılan CLI giriş noktası.

Temel bileşenler

Bağımsız değişkenler:
  file              wasm dosya yolu (gerekli)
  --version, -v     sürümü yazdır ve çık
  --func            çağrılacak dışa aktarılan işlev adı (varsayılan: _start)
  --func-args       tekrar eden; dize olarak bağımsız değişken değerleri
  --wasi            WASI'yi etkinleştirmek için 'preview1'
  --wasi-envs       'ANAHTAR=DEĞER' çiftleri
  --wasi-dirs       'wasm_yolu:host_yolu' dizin eşlemeleri
  --wasi-args       WASI programı için argv

İç mantık

İki kod yolu:

  1. main_wasi()--wasi preview1 mevcutsa:

    • Runtime ve Preview1 nesnesi oluşturur
    • Host işlevleri kaydetmek için wasi.bind(runtime) çağırır
    • runtime.instance_from_file(file) çağırır
    • _start'ı çağırmak için wasi.main(runtime, inst) çağırır
    • Süreç çıkış koduyla sys.exit(code)
  2. main_wasm() — düz Wasm:

    • Runtime oluşturur, modülü başlatır
    • Adlandırılmış dışa aktarmayı çözer
    • --func-args dizelerini yazılı Python değerlerine dönüştürür
    • runtime.invocate(...) çağırır ve sonuç listesini yazdırır

6.8 pywasm/wasi.py

Dosya amacı

WASI Preview 1 ABI'nin Python sınıfı olarak eksiksiz uygulaması. wasm32-wasip1 hedefine karşı derlenen Wasm programlarının çağıracağı 45 sistem çağrısı benzeri host işlevi sağlar.

Önemli: Platform kısıtlaması

wasi.py, fcntl (POSIX) ve os işlevlerine dir_fd= bağımsız değişkenleri kullanır. Bu modül yalnızca Linux ve macOS'ta içe aktarılır.

Temel bileşenler

class Preview1.File (veri sınıfı)

Hem host tarafında hem de WASI tarafında meta verilerle açık bir dosya tanımlayıcısını temsil eder:

Alan Açıklama
host_fd İS dosya tanımlayıcısı tamsayısı
host_flag İS bayrakları (O_RDONLY, O_APPEND, vb.)
host_name Host dosya sistemindeki mutlak yol
host_status FILE_STATUS_OPENED veya FILE_STATUS_CLOSED
pipe Okuma/yazmaları yönlendirmek için isteğe bağlı io.BytesIO
wasm_fd WASI dosya tanımlayıcısı numarası
wasm_flag WASI fdflags
wasm_name Wasm programının gördüğü yol
wasm_rights_base İzin verilen işlemlerin bit maskesi
wasm_rights_root Devralınabilir hakların bit maskesi
wasm_status WASI fd durumu
wasm_type WASI dosya türü (normal, dizin, soket, vb.)
WASI işlev kategorileri
Kategori İşlevler
Bağımsız değişkenler/Ortam args_get, args_sizes_get, environ_get, environ_sizes_get
Saat clock_res_get, clock_time_get
Dosya tanımlayıcısı fd_advise, fd_allocate, fd_close, fd_datasync, fd_fdstat_get, fd_fdstat_set_flags, fd_fdstat_set_rights, fd_filestat_get, fd_filestat_set_size, fd_filestat_set_times, fd_pread, fd_prestat_get, fd_prestat_dir_name, fd_pwrite, fd_read, fd_readdir, fd_renumber, fd_seek, fd_sync, fd_tell, fd_write
Yol path_create_directory, path_filestat_get, path_filestat_set_times, path_link, path_open, path_readlink, path_remove_directory, path_rename, path_symlink, path_unlink_file
Yoklama poll_oneoff
Süreç proc_exit, proc_raise
Rastgelelik random_get
Zamanlayıcı sched_yield
Soket sock_accept, sock_recv, sock_send, sock_shutdown
Yol korumalı alan oluşturma

Her path_* işlevi, yol geçiş girişimlerini (örn. ../../etc/passwd) algılamak için help_escp(wasm_name, user_path) çağırır. Normalleştirilmiş yol önceden açılmış dizinden kaçarsa ERRNO_PERM döndürülür.

proc_exit davranışı
def proc_exit(self, _, args):
    if self.return_on_exit:
        raise Exception(SystemExit, args[0])   # main() tarafından yakalanır
    sys.exit(args[0])

return_on_exit = 1 varsayılan olarak — bu Python programının Wasm programı çıktıktan sonra devam etmesini sağlar. 0 olarak ayarlanması Python sürecinin sona ermesine neden olur.


7. Çalıştırma Akışı

7.1 Kütüphane kullanımı başlangıç dizisi

import pywasm
│
├── arith.py modülü çalıştırılır   → i8, u8, …, f32, f64 tekil nesneleri oluşturur
├── leb128.py modülü çalıştırılır  → u, i tekil nesneleri oluşturur
├── log.py modülü çalıştırılır     → lvl = 0
├── opcode.py modülü çalıştırılır  → 437 sabit + name sözlüğü
├── core.py modülü çalıştırılır    → yalnızca sınıf tanımları
└── wasi.py içe aktarılır (yalnızca Linux/macOS)

runtime = pywasm.core.Runtime()
│
└── Machine()
    └── Store()
    └── Stack()
    runtime.imports = {}

runtime.instance_from_file('module.wasm')
│
├── open('module.wasm', 'rb')
├── ModuleDesc.from_reader(f)
│   ├── Sihirli + sürüm kontrol et
│   └── Bölümler üzerinde döngü (type, import, func, table, mem, global, export, start, elem, code, data)
│
└── Runtime.instance(module)
    └── Machine.instance(module, extern_listesi)
        ├── İçe aktarmaları doğrula
        ├── Global başlatma ifadelerini değerlendir
        ├── Machine.allocate(module, extern, globin, elemin)
        ├── Aktif öğe segmentlerini çalıştır
        ├── Aktif veri segmentlerini çalıştır
        └── Başlangıç işlevini çalıştır
        → ModuleInst döndür

7.2 İşlev çağrısı dizisi

runtime.invocate(module, 'fibonacci', [10])
│
├── 'fibonacci'yi module.exps'de ara → func_addr
├── func_inst = store.func[func_addr] al
├── func_args = [ValInst.from_i32(10)] oluştur
└── Machine.invocate(func_addr, func_args)
    ├── Sentinel Frame it
    ├── LocalsInst oluştur
    ├── Gerçek Frame ve Label(carry=3) it
    └── Machine.evaluate()
        Label yığını boşalana kadar döngü:
            label.instr[label.index++]'dan talimat al
            match instr.opcode:
                ... gönder ...
        ← label yığını boş
    Değer yığınından dönüş değerlerini çıkar
    Sentinel Frame'i çıkar
    → [55] döndür (fibonacci(10))

8. API Dokümantasyonu

8.1 Runtime (birincil genel arabirim)

Runtime()

Yeni, izole bir WebAssembly çalışma zamanı oluşturur.

runtime = pywasm.core.Runtime()

runtime.imports

runtime.imports: dict[str, dict[str, Extern]]

İçe aktarma kaydı. Başlatmadan önce doldurun:

runtime.imports['env'] = {
    'my_func': runtime.allocate_func_host(type, callable),
}

runtime.allocate_func_host(type, func) → Extern

Python çağrılabilirini WebAssembly host işlevi olarak kaydeder.

def my_print(machine, args):
    print(f"Wasm diyor ki: {args[0]}")
    return []

extern = runtime.allocate_func_host(
    pywasm.core.FuncType([pywasm.core.ValType.i32()], []),
    my_print
)

runtime.instance_from_file(path) → ModuleInst

Bir .wasm ikilisi yükler ve başlatır. Tüm içe aktarmaları runtime.imports'tan çözer.

Hatalar: Sihirli/sürüm uyuşmazlığı, içe aktarmaların karşılanamaması veya tür doğrulama başarısızlığında AssertionError.

runtime.invocate(module, func, args) → list

Dışa aktarılan işlevi ada göre çağırır.

result = runtime.invocate(m, 'fibonacci', [10])
# result == [55]

runtime.exported_memory(module, name) → MemInst

Dışa aktarılan doğrusal belleğe doğrudan erişim sağlar.

mem = runtime.exported_memory(m, 'memory')
data = mem.get(ptr, length)      # bayt oku
mem.put(ptr, bytearray(...))     # bayt yaz

runtime.exported_global(module, name) → GlobalInst

Dışa aktarılan bir globalin geçerli değerine erişim sağlar.

g = runtime.exported_global(m, 'my_global')
print(g.data.into_i32())
g.data = pywasm.core.ValInst.from_i32(99)   # değiştirilebilir globali değiştir

8.2 API'de kullanılan temel türler

Tür Oluşturma Açıklama
ValType.i32() Sınıf yöntemi 32 bitlik tamsayı türü
ValType.i64() Sınıf yöntemi 64 bitlik tamsayı türü
ValType.f32() Sınıf yöntemi 32 bitlik kayan nokta türü
ValType.f64() Sınıf yöntemi 64 bitlik kayan nokta türü
ValType.v128() Sınıf yöntemi 128 bitlik SIMD türü
FuncType(args, rets) Yapıcı İşlev imzası
Limits(n, m) Yapıcı Min/max sınırları (m=0 sınırsız anlamına gelir)
MemType(limits) Yapıcı Bellek türü
TableType(valtype, limits) Yapıcı Tablo türü
GlobalType(valtype, mut) Yapıcı Global türü (mut: 0=sabit, 1=değiştirilebilir)
ValInst.from_i32(n) Sınıf yöntemi i32 değeri oluştur
ValInst.from_f64(n) Sınıf yöntemi f64 değeri oluştur
ValInst.zero(type) Sınıf yöntemi Verilen türde sıfır değeri oluştur

9. Yapılandırma Dokümantasyonu

9.1 Hata ayıklama günlük kaydı

import pywasm
pywasm.log.lvl = 1   # ayrıntılı hata ayıklama çıktısını etkinleştir

lvl'yi sıfırdan farklı herhangi bir tamsayıya ayarlamak stdout'a bölüm başına ve talimat başına izlemeyi etkinleştirir.

9.2 Bellek sınırı

Machine.evaluate, memory_grow'u 1024 sayfaya (64 MiB) sabitler. core.py değiştirilmeden çalışma zamanında yapılandırılamaz:

# core.py:2008
cnda = size + incr <= 1024   # sabit üst sınır — artırmak için bunu değiştir

9.3 Çağrı yığını derinliği

Machine.evaluate_call, 1024 çerçeve sınırı uygular:

assert len(self.stack.frame) < 1024

9.4 WASI return_on_exit

wasi = pywasm.wasi.Preview1(args, dirs, envs)
wasi.return_on_exit = 0   # istisna yerine sys.exit() çağırmak için 0 olarak ayarla

9.5 WASI stdout/stdin yakalama

import io
wasi.fd[1].pipe = io.BytesIO(bytearray())   # stdout → arabellek
wasi.fd[0].pipe = io.BytesIO(b'giriş verisi') # stdin ← arabellek

9.6 Ortam değişkenleri ve dizin eşlemeleri (WASI)

wasi = pywasm.wasi.Preview1(
    args=['program.wasm', '--bayrak'],
    dirs={'/korumalı_alan': '/host/yolu/dizin'},  # wasm_yolu: host_yolu
    envs={'HOME': '/korumalı_alan', 'LANG': 'C'}
)

10. Derleme ve Dağıtım

10.1 PyPI'den kurulum

pip install pywasm

10.2 Kaynaktan kurulum (düzenlenebilir)

git clone https://github.com/libraries/pywasm
cd pywasm
pip install --editable .

10.3 Dağıtım paketi oluşturma

pip install build
python -m build          # dist/pywasm-2.2.3.tar.gz ve dist/pywasm-2.2.3-py3-none-any.whl oluşturur

10.4 Wasm örnekleri derleme (yalnızca geliştirici)

wasm32-unknown-unknown ve wasm32-wasip1 hedefleriyle Rust gerektirir:

rustup target add wasm32-unknown-unknown wasm32-wasip1
python script/build_wabt.py     # wabt araçlarını indir
python script/build_example.py  # tüm Rust örneklerini derle

10.5 Testleri çalıştırma

python script/build_wabt.py   # tek seferlik
python script/build_spec.py   # spec testlerini klonla + derle
python script/build_wasi.py   # WASI test paketini klonla

python test/example.py        # tüm örnekleri çalıştır
python test/main.py           # CLI duman testleri
python test/spec.py           # spec uyumluluğu (yavaş)
python test/wasi.py           # WASI uyumluluğu

10.6 CI/CD boru hattı

GitHub Actions (.github/workflows/develop.yaml):

  • Her push ve PR açmada tetiklenir
  • Matris: macOS, Ubuntu, Windows × Python 3.14
  • Adımlar: checkout → setup-python → build_wabt → pywasm kurulumu → testleri oluştur → tüm testleri çalıştır
  • Dağıtım adımı yok (PyPI yayınlama manueldir)

10.7 Sürüm stratejisi

Sürüm iki yerde ayarlanır:

  1. pyproject.toml: version = "2.2.3"
  2. pywasm/__init__.py: version = '2.2.3'

Otomatik sürüm artışı yoktur. Bir geliştirici, yayınlamadan önce her iki dosyayı da manüel olarak güncellemelidir.


11. Güvenlik Analizi

11.1 Güven sınırları

Güvenilmez: .wasm dosya içeriği
Güvenilir:   Python host kodu, WASI önceden açılan dizin yolları

11.2 Korumalı alan özellikleri

Bellek erişimi: Tüm MemInst.data erişimleri, açık sınır doğrulamaları ile Python dilimleme dizinlemesi kullanır. Sınır dışı erişimler AssertionError (tuzak) yükseltir, segfault değil.

Dosya sistemi: WASI path_* işlevleri, dizin geçişini önlemek için help_escp çağırır. Önceden açılan dizinler korumalı alan sınırını tanımlar.

Ağ: Soket işlemleri, fd tablosu aracılığıyla var olan bir soketin iletilmesini gerektirir. Wasm programı bağımsız olarak yeni bağlantılar başlatamaz.

Süreç yalıtımı: Wasm programı, işlemleri başlatamaz, paylaşılan kütüphaneler yükleyemez veya Python yorumlayıcısının nesnelerine doğrudan erişemez.

11.3 Olası güvenlik açıkları

Risk Önem Notlar
Sınır kontrolü için assert Orta python -O ile assert ifadeleri devre dışı bırakılır. Optimize edilmiş pywasm çalıştırmak tüm güvenlik kontrollerini devre dışı bırakır.
LEB128 sonsuz döngü Düşük Eksik durdurma baytına sahip hatalı biçimlendirilmiş .wasm sonsuza kadar döner. Maksimum bayt sayısı koruması yok.
Sabit kodlanmış bellek sınırı Düşük 64 MiB üst sınırı atlatılabilir.
help_escp güvenilirliği Orta Yol kaçış kontrolü os.path.normpath ve dize öneki eşleştirmesi kullanır. Büyük/küçük harf duyarsız dosya sistemlerinde kaçışlar mümkün olabilir.
random.randbytes Düşük Python'un random modülü (Mersenne Twister) kullanır, kriptografik açıdan güvenli RNG değil.
Kaynak sınırı yok Orta Kontrolden çıkan bir Wasm programı CPU zamanını ve Python heap'ini tüketebilir.

12. Performans Analizi

12.1 Temel özellikler

pywasm, JIT derleyicisi olmayan bir yorumlayıcıdır. Her WebAssembly talimatı bir Python işlev çağrısıdır. Yaklaşık büyüklük sırası:

  • Yerel Wasmtime: ~1 ns/talimat
  • CPython üzerinde pywasm: ~1 µs/talimat (1000× daha yavaş)
  • PyPy üzerinde pywasm: ~100 ns/talimat (CPython'dan ~10× daha hızlı)

12.2 Birincil darboğazlar

Darboğaz Açıklama
match instr.opcode gönderimi Python'un yapısal desen eşleştirmesi bir anahtar tablosu kadar hızlı değildir.
ValInst tahsisi Çoğu talimat yeni bir ValInst (16 baytlık bytearray + tür) oluşturur. Bu önemli GC baskısı oluşturur.
SIMD liste kavrayışları Her SIMD talimatı 16 baytlık bytearray'i Python listesine dönüştürür, öğe bazında işlem uygular ve yeniden paketler.
arith.clz/ctz/popcnt O(64) yineleme için saf Python bit döngüleri.
Hata ayıklama modu ek yükü Her talimat için f-string biçimlendirme ve print() çağrıları.

12.3 Ölçeklenebilirlik

pywasm tek iş parçacıklıdır. threading veya asyncio desteği yoktur.

12.4 Optimizasyon fırsatları

Fırsat Beklenen kazanım
popcnt için int.bit_count() kullan O(N) döngüsünü yerel yöntemle değiştirir
label.instr[label.index]'i yerel değişkende önbelleğe al Yineleme başına öznitelik aramalarını azaltır
Talimat listesini tuple dizisi olarak önceden hesapla Inst nesne ek yükünü azaltır
Sık çağrılan işlevleri Python bayt koduna derle (JIT) "JIT dostu" tasarım yorumu bunu amaçladığını ima eder
ValInst nesnelerini havuzla (ortak değerler için flyweight) Tahsis/GC baskısını azaltır
Bellek dilimleri için memoryview kullan evaluate_mem_load'da bytearray kopyasını önler

13. Geliştirici Kılavuzu

13.1 Ön koşullar

Araç Sürüm Amaç
Python ≥ 3.12 Çalışma zamanı ve geliştirme
Rust + cargo kararlı Örnek .wasm ikilileri derle
wasm32 hedefleri rustup target add wasm32-unknown-unknown wasm32-wasip1
WABT (otomatik indirilir) 1.0.41 Spec testleri için wast2json
Git herhangi Spec ve WASI test depolarını klonla

13.2 İlk kurulum

# 1. Klonla
git clone <depo>
cd pywasm

# 2. Kur (düzenlenebilir)
pip install --editable .

# 3. Geliştirici araçlarını indir
python script/build_wabt.py

# 4. İsteğe bağlı: Rust örneklerini derle (Rust gerektirir)
python script/build_example.py

# 5. Temel testleri çalıştır
python test/example.py
python test/main.py

13.3 Hızlı duman testi çalıştırma

import pywasm
runtime = pywasm.core.Runtime()
m = runtime.instance_from_file('example/fibonacci/bin/fibonacci.wasm')
r = runtime.invocate(m, 'fibonacci', [10])
assert r == [55], r
print("TAMAM")

13.4 Hata ayıklama izlemesini etkinleştirme

import pywasm
pywasm.log.lvl = 1
runtime = pywasm.core.Runtime()
m = runtime.instance_from_file('example/fibonacci/bin/fibonacci.wasm')
r = runtime.invocate(m, 'fibonacci', [3])
# Çıktı:
# 2026/06/07 12:00:00 pywasm: bölüm type [i32] -> [i32]
# 2026/06/07 12:00:00 pywasm: invocate 0 [i32 3]
# ...

13.5 Host işlev enjekte etme

import pywasm

def my_log(machine: pywasm.core.Machine, args: list) -> list:
    print(f"[WASM LOG] değer={args[0]}")
    return []

runtime = pywasm.core.Runtime()
runtime.imports['env'] = {
    'log': runtime.allocate_func_host(
        pywasm.core.FuncType([pywasm.core.ValType.i32()], []),
        my_log
    )
}
m = runtime.instance_from_file('my_module.wasm')
runtime.invocate(m, 'run', [])

Karşılık gelen Rust kodu içe aktarmayı bildirir:

extern "C" { fn log(value: i32); }

13.6 Doğrusal belleği okuma / yazma

mem = runtime.exported_memory(m, 'memory')

# 1000 adresinde null sonlandırılmış C dizesi oku
ptr = 1000
end = mem.data.index(0, ptr)
s = mem.data[ptr:end].decode('utf-8')

# 2000 adresine 4 bayt yaz
mem.put(2000, bytearray([0x01, 0x02, 0x03, 0x04]))

13.7 Yeni işlem kodu ekleme

  1. opcode.py'ye sabiti ekle:

    my_new_op = 0xXX
    name[my_new_op] = 'my_new.op'
    
  2. core.py'deki Inst.from_reader'a çözme mantığı ekle:

    case pywasm.opcode.my_new_op:
        o.args.append(pywasm.leb128.u.decode_reader(r)[0])
    
  3. core.py'deki Machine.evaluate'a çalıştırma mantığı ekle:

    case pywasm.opcode.my_new_op:
        a = self.stack.value.pop().into_i32()
        b = ValInst.from_i32(my_operation(a))
        self.stack.value.append(b)
    

13.8 Yeni WASI sistem çağrısı ekleme

  1. Preview1 sınıfına sabitler ekle (errno, bayraklar, vb.)
  2. Uygulama yöntemini yaz:
    def my_syscall(self, m: pywasm.core.Machine, args: list[int]) -> list[int]:
        if self.help_badf(args[0]):
            return [self.ERRNO_BADF]
        # ... uygulama ...
        return [self.ERRNO_SUCCESS]
    
  3. Preview1.bind()'a kaydet:
    ['my_syscall', [i32, i32], [i32], self.my_syscall],
    

13.9 Spec testlerini çalıştırma

python script/build_spec.py   # tek seferlik
python test/spec.py

13.10 Başarısız spec testinde hata ayıklama

  1. test/spec.py'de pywasm.log.lvl = 1 ayarla
  2. all_test'i tek bir dosyaya filtrele: all_test = ['res/spec/test/core/i32.json']
  3. JSON komutlarını belirli bir test durumu dizinine filtrele

14. İyileştirme Önerileri

14.1 Mimari iyileştirmeler

Öneri Gerekçe
Çözümleyiciyi core'dan ayır ModuleDesc ve tüm *Desc sınıfları makinenin yanında core.py'de yaşar. decoder.py'ye bölmek gezinmeyi iyileştirir.
Uygun istisna hiyerarşisi tanıt Tüm hatalar şu anda AssertionError (tuzaklar için) veya yalın Exception kullanır. Bir WasmTrap, WasmLinkError, WasiError hiyerarşisi çağırıcıların hata türlerini ayırt etmesini sağlar.
Bellek sınırını yapılandırılabilir yap 1024 sayfa sabit üst sınırı ve 1024 çerçeve derinlik sınırı core.py'deki sihirli sayılar değil, Runtime'ın parametreleri olmalıdır.
İş parçacığı güvenli çok modüllü çalıştırma Store'un tahsis listeleri etrafında threading.Lock, çok iş parçacıklı yerleştirici senaryolarında eşzamanlı başlatmaya izin verir.

14.2 Kod kalitesi iyileştirmeleri

Öneri Gerekçe
pyproject.toml'e python_requires = ">=3.12" ekle Eski Python'da kafa karıştırıcı başarısızlıkları önler.
Sürümü tek kaynaktan senkronize et __init__.py'de importlib.metadata.version('pywasm') kullan veya sürüm dosyası kullan.
assert'i açık kontrollerle değiştir python -O ile assert devre dışı bırakılır. Güvenlik açısından kritik sınır kontrolleri if ... raise ... olmalıdır.
wasi.py yöntemlerine tür ipuçları ekle args: list[int] ipucu çoğu sistem çağrısı için doğrudur, ancak eksiksiz doğruluk için `list[int
SIMD işlem kodu işlemeyi ayır evaluate()'daki 1200+ SIMD durumu, ana döngünün boyutunu azaltmak için evaluate_simd(instr) yardımcısına çıkarılabilir.

14.3 Sürdürülebilirlik iyileştirmeleri

Öneri Gerekçe
Docstring ekle Kod tamamen satır içi yorumlara dayanır. Runtime, Machine, Store, Preview1 üzerindeki docstring'ler IDE entegrasyonunu iyileştirir.
Değişiklik günlüğü tanıt CHANGELOG.md yoktur. Katkıda bulunanlar sürümler arasında neyin değiştiğini göremez.
WABT sürümünü CI'da sabitle build_wabt.py sabit kodlanmış v1.0.41 indirir. Bu, spec checkout tarafından beklenen sürümle eşleşmelidir.

14.4 Performans iyileştirmeleri

Öneri Öncelik Beklenen kazanım
arith.popcntint.bit_count() ile değiştir Düşük Popcount için 64× hız artışı
Ortak ValInst nesnelerini havuzla Orta GC baskısını ~%30 azalt
Talimatları (opcode, *args) demeti olarak temsil et Orta Daha küçük nesneler, daha az öznitelik araması
evaluate() için isteğe bağlı Cython uzantısı ekle Yüksek CPU'ya bağlı kod için 5–50× hız artışı
compile() / exec() aracılığıyla temel JIT uygula Çok Yüksek CPython'da PyPy performansıyla eşleşebilir

14.5 Güvenlik iyileştirmeleri

Öneri Gerekçe
Bellek OOB için assert'i raise ile değiştir python -O assert'i devre dışı bırakır; OOB erişimi host belleği bozar.
random_get için os.urandom kullan random.randbytesos.urandom ile değiştirerek "yüksek kaliteli rastgelelik" WASI spec gereksinimini karşıla.
WASI için yol geçiş testleri ekle help_escp mantığı uç durumlara karşı test edilmelidir: sembolik bağlantılar, .. bileşenleri, Windows yolları, Unicode normalleştirme.
LEB128 maksimum uzunluk koruması ekle Hatalı girişte sonsuz döngüleri önlemek için LEB128 okumalarını ceil(64/7) = 10 bayta sınırla.

Dokümantasyon, pywasm v2.2.3 kod analizi ile oluşturulmuştur. Tüm satır referansları analiz zamanındaki depo durumuna dayanmaktadır.

Tüm Yazılar