Jade VM — Instruction Set v0.1 (Core + Extended)¶
Normativ (v0.1)
Diese Spezifikation definiert das ausführbare Kern-Instruktionsset der Jade VM und die Regeln, wie höhere Konstrukte in dieses Set abgesenkt werden.
Ältere Entwürfe (z.B. Jade VM – Core Instruction Set (Draft, with HALT)) gelten als archivierter Kontext und sind nicht normativ.
0. Ziele und Nicht-Ziele¶
Ziele
- Ein kleines, stabiles Execution-Core-Instruktionsset, das die VM direkt ausführt.
- Eine klare Trennung: Extended Layer existiert nur in IR/Frontend und wird vor Verifikation vollständig zu Core abgesenkt.
- Ein Operand- und Encoding-Modell, das:
- kompakt ist,
- Debug-Infos getrennt hält,
- Optimierungen wie Inline Caches / Quickening ermöglicht, ohne das Opcode-Set zu sprengen.
Nicht-Ziele
- Kein „Opcode pro Feature“-Zoo (Profiling/Bench/Tests sind kein VM-Opcode-Thema).
- Keine Festlegung auf JIT/AOT. Die Spez beschreibt das Semantikmodell, nicht die Codegen-Strategie.
1. Begriffe¶
- Core (Execution Core): minimaler Befehlssatz, der von der VM direkt ausgeführt wird.
- Extended Layer: höhere Instruktionen (Sugar, IR-Komfort), die vor Verifikation vollständig in Core + Runtime-Calls transformiert werden.
- Verifier: prüft ein Modul nach dem Lowering auf Invarianten (CFG, Typ-/Operandregeln, Stack/Reg-Grenzen, Termination).
- Function Prototype (Proto): kompiliertes Funktionsobjekt (Bytecode + Const-Pool + Register-Layout + Debug-Info).
2. Architektur: Core vs Extended¶
Die Trennung ist verpflichtend:
- Extended-Instruktionen dürfen im Frontend/IR existieren.
- Vor Verifikation und Ausführung müssen sie komplett eliminiert sein.
- Plugins dürfen Extended erweitern, aber nicht den Core.
(Design-Konstitution: Core vs Extended ist ein zentrales Stabilitätsprinzip.)
3. Ausführungsmodell (Register-VM)¶
3.1 Registerdatei und Frames¶
- Jede Funktion besitzt eine feste Anzahl Register
R0..R(n-1). - Ein Call erzeugt einen neuen Frame mit eigener Registerdatei.
- Rückgabewert ist ein einzelnes
JadeValue.
Calling Convention v0.1 (einfach, robust):
Call { dst, func, argsBase, argc }funcenthält ein Callable (Funktionsproto, Closure, native/builtin).- Argumente liegen in aufeinanderfolgenden Registern ab
argsBase. - Ergebnis wird in
dstgeschrieben.
3.2 Werte¶
JadeValue ist ein getaggter Wertcontainer (Immediate oder Handle in die Memory Engine).
Details (Handles, Arenas, Policies) sind in den Runtime-Spezifikationen beschrieben.
4. Encoding & Operanden¶
4.1 Grundformat¶
Ein Core-Instruktionsstream besteht aus:
opcode: u8oderu16(Implementationswahl)- 0..k Operanden (fixed oder variable length)
Normative Anforderung:
- Decoding muss deterministisch sein.
- Verifier muss jede Instruktion ohne Ausführung vollständig validieren können.
4.2 Operanden-Typen¶
Reg(u16)— RegisterindexConst(u32)— Index in den Konstantenpool der Funktion (oder des Protos)Jump(i32)— relativer Sprung-Offset oderBlockId(u32)(Implementationswahl, aber im Modul konsistent)Upval(u16)— Upvalue-Index innerhalb einer Closure-UmgebungImm— kleine Immediate-Varianten (optional, s.u.)
Hinweis: Viele „kleine Convenience“-Loads (LoadNull, LoadI8, …) sind als Extended erlaubt.
5. Debug-Informationen (SourceLoc)¶
Core-Instruktionen tragen semantisch ein SourceLoc, aber nicht inline im Opcode-Stream.
Normativ:
- Debug-Infos werden als Side-Table gespeichert:
pc -> SourceLoc. - Builds dürfen Debug-Infos vollständig strippen.
- Runtime-Fehler (
Trap) müssen im Debug-Build eine Quellposition reporten können.
6. Core Instruction Set v0.1¶
6.1 Konvention¶
Notation:
dst, src, lhs, rhs, obj, arr, idx, cond, func, argsBasesind Registeroperanden.kist ein Const-Index.jist ein Jump-Ziel.
6.2 Constants¶
-
LoadK dst, k
Lädt Konstantekindst. -
LoadBool dst, immBool
Lädttrue/falseindst.
Optional (Extended, empfohlen): LoadI{8,16,32}, LoadNull, LoadUnit.
6.3 Arithmetic (numerisch)¶
Add dst, lhs, rhsSub dst, lhs, rhsMul dst, lhs, rhsDiv dst, lhs, rhsMod dst, lhs, rhsNeg dst, src
Semantik:
- Operanden müssen numerisch kompatibel sein.
- Overflow/NaN/Division-by-zero Verhalten ist durch den jeweiligen Zahltyp definiert.
- Unzulässige Operationen führen zu
Trap(oder werden statisch ausgeschlossen).
6.4 Vergleich & Bool¶
Eq dst, lhs, rhs→bool-
Lt dst, lhs, rhs→bool -
Not dst, src
Hinweis (normativ):
- Short-Circuit-Logik (
and/or) ist Extended und wird überJmpIf/Jmpabgesenkt.
Hinweis: Ne/Le/Gt/Ge sind Extended und werden auf Eq/Lt/Not abgesenkt.
6.5 Control Flow¶
Jmp jJmpIf cond, j
springt, wenncond == true.
Verifier-Anforderung: Sprünge dürfen nur auf gültige Ziele innerhalb derselben Funktion zeigen.
6.6 Functions¶
Call dst, func, argsBase, argcReturn src
Return: beendet den aktuellen Frame und liefert src an den Caller.
Tailcalls: Extended (z.B. TailCall) und werden zu Call + Return oder einer VM-Optimierung abgesenkt.
6.7 Closures & Upvalues¶
-
Closure dst, kProto
erzeugt eine Closure aus einem Funktionsproto (Const-Pool Eintrag). -
LoadUp dst, up StoreUp up, srcCloseUp baseReg
CloseUp: schließt alle offenen Upvalues, die auf Stack-Slots ≥ baseReg zeigen.
6.8 Aggregates (Struct/Array)¶
NewStruct dst, kTypeIdGetField dst, obj, kField-
SetField obj, kField, src -
NewArray dst, lenReg GetIndex dst, arr, idxRegSetIndex arr, idxReg, src
Hinweis: Maps/Sets/Listen sind Library-level und werden über Runtime-Calls/FFI implementiert.
6.9 Moves & Lifetime¶
Move dst, srckopiert den Wert vonsrcnachdstund markiertsrcals nicht mehr verwendbar.
Normativ:
- Der Verifier stellt sicher, dass src nach Move nicht mehr gelesen wird.
- Die VM darf in Debug/Profiling Builds src poisonen und Use-after-move zu Trap machen.
- In Release ist Use-after-move ein Verifier-Fehler (nicht „UB“).
Drop srcsignalisiert End-of-Lifetime. Für Handles: Destruction/RC-Update gemäß Policy.
Verifier/Runtime:
- Use-after-drop ist in Release ein Verifier-Fehler; in Debug/Profiling darf es zusätzlich als Runtime-Fehler (
Trap) detektiert werden. - Copy/Clone ist Extended und wird über type-spezifische Calls + Move/Drop ausgedrückt.
6.10 Termination¶
-
Trap kReason
beendet mit Runtime-Fehler. Erzeugt strukturierte Error-Info (Reason + SourceLoc + Stacktrace wenn aktiv). -
Halt
normale Terminierung des aktuellen Tasks/Programms (genaue Semantik über Scheduler-Spezifikation).
7. Verifier-Invarianten (v0.1)¶
Der Verifier prüft mindestens:
1) Lowering vollständig: keine Extended-Instruktionen im Core-Stream.
2) CFG-Korrektheit:
- Sprünge auf gültige Ziele,
- Basic Blocks enden in Terminator (Jmp, JmpIf, Return, Trap, Halt) oder fallthrough ist explizit erlaubt (Implementationswahl, aber konsistent).
3) Operand-Grenzen:
- Registerindex < regCount,
- Constindex < constCount,
- Upvalindex < upvalCount.
4) Stack/Frame-Regeln:
- Call/Return korrekt verschachtelt.
5) Debug-Info Konsistenz: (nur Debug-Build) pc→SourceLoc vollständig für trap-relevante Stellen.
8. Intrinsics, Profiling, Benchmarks (ohne Opcode-Explosion)¶
8.1 Grundsatz¶
- Tests/Benchmarks sind Runner/Framework-Themen, nicht VM-Opcodes.
- Profiling/Tracing darf nicht zu einem Opcode-Zoo führen.
8.2 Mechanismus v0.1¶
Es gibt zwei zulässige Implementationsstrategien (beide normativ kompatibel):
A) Builtin/Intrinsic Calls über Call (kein neuer Opcode):
@profilewird zu Aufrufen eines compiler-known builtins abgesenkt:__intrinsic.prof_begin(labelId)__intrinsic.prof_end()
B) Ein generischer Intrinsic-Opcode (max. 1 zusätzlicher Opcode in der VM):
Intrinsic subcode, a, b- Subcodes:
PROF_BEGIN,PROF_END,COUNTER,INSTANT,MONO_NS,BLACK_BOX, …
Normativ: In release werden Instrumentationsknoten per Profile/CFG-Pruning entfernt, so dass im Production-Bytecode nichts verbleibt.
9. Extended Lowering Patterns (v0.1, informativ)¶
Diese Patterns sind informativ (nicht normativ), helfen aber dabei, das Core-Set klein zu halten.
9.1 Short-Circuit Bool¶
a and b (Extended) wird typischerweise zu:
- eval
a→cond JmpIf cond, L_eval_belse →dst = false; Jmp L_endL_eval_b:evalb→dstL_end:
a or b analog.
9.2 „_K“ Superinstructions¶
Sequenzen wie LoadK tmp, k; GetField dst, obj, tmp können im IR zu GetFieldK dst, obj, k fusioniert werden (Extended) und vor Verifikation wieder auf Core zurückgehen.
Ziel: weniger Dispatch/Registers, ohne Core-Opcodes zu vermehren.
10. Quickening & Inline Caches (Implementation Notes)¶
Quickening ist eine VM-Optimierung, keine Semantik.
Empfehlung:
- Eligible Instructions:
GetField,SetField,Call,GetIndex,SetIndex, ggf. numerische Ops. - Die VM darf pro Instruction-Site einen kleinen Inline-Cache (mono/poly) führen.
- Bei Guard-Fail: Fallback auf generischen Pfad; optional Re-Spezialisierung.
Wichtig:
- Cache-Daten dürfen die beobachtbare Semantik nicht ändern.
- Profiling/Debug können Quickening deaktivieren oder einfrieren, um Messungen stabil zu halten.
11. Beziehung zu archivierten Entwürfen¶
Der frühere Draft Jade VM – Core Instruction Set (Draft, with HALT) beschreibt bereits die Idee eines minimalen Cores und wird als historischer Kontext aufbewahrt. Dieses Dokument ersetzt ihn als normativer Stand (v0.1).