Compiler & JIT • Juni 2026

Sprint 283: In-Memory JIT-Kompilierung & Ausführbarer Maschinencode ⚡

Willkommen zu Sprint 283 und 291! In dieser Beitragsreihe beleuchten wir den Meilenstein der KnotenCore-JIT-Kompilierung. Um eine maximale Recheneffizienz für autonome KI-Agenten zu erreichen, übersetzen wir AST-Deklarationen nun direkt im Arbeitsspeicher in rohe x86_64-Assemblerbefehle und führen diese ohne Zwischenprozess direkt auf der Host-CPU aus.

🧠 Dynamische Allokation von RWX-Speicherseiten

Moderne Betriebssysteme verbieten standardmäßig die Ausführung von Code aus normalen Speichersegmenten (wie dem Heap oder Stack) aus Sicherheitsgründen (W^X: Write XOR Execute). Um JIT-kompilierten Maschinencode ausführen zu können, müssen wir dem Betriebssystem explizit mitteilen, dass ein bestimmtes Speichersegment ausführbar sein soll.

Dazu verwenden wir in Sprint 283 das memmap2-Crate:

  1. Wir allokieren eine anonyme Speicherseite über MmapMut::map_anon(size).
  2. Wir kopieren die generierten Byte-Sequenzen der x86_64-Maschinenbefehle in diese Seite.
  3. Wir konfigurieren die Speicherseite mithilfe von make_exec() als ausführbar.
  4. Wir transmutieren den Zeiger auf die Speicherseite in einen Rust-Funktionszeiger (extern "C" fn() -> i64) und rufen diesen auf.

🛠️ Register-Korrekturen & Testabsicherung (Sprint 291)

Während des Audits von Sprint 290 stellten wir fest, dass die Addition bei JIT-Befehlen das falsche Register pushte. Bei OpCode::Add wurde zwar add rcx, rax ausgeführt (wodurch das Ergebnis im rcx-Register abgelegt wurde), der Emitter pushte danach jedoch den unveränderten Operanden rax zurück auf den Stack.

In Sprint 291 wurde dies durch die Implementierung von emit_push_rcx korrigiert, wodurch JIT-Additionen mathematisch exakt auf der CPU berechnet werden. Der neue Test test_jit_native_execution_add verifiziert diese Korrektheit direkt auf Hardwareebene (10 + 5 = 15).

🧪 Verifizierung & Performance-Impact

Durch das Ausführen von JIT-Kompilaten direkt im Arbeitsspeicher entfällt jeglicher FFI- und Interpreter-Overhead. Berechnungen und mathematische Schleifen laufen mit der vollen Bare-Metal-Geschwindigkeit der CPU. Der Integrationstest-Lauf im CI prüft diese Pipeline bei jedem Push ab und sichert die JIT-Integrität ab.