----- # High-Performance Backend (Bytecode VM) **Datum:** 21.11.2025 **Status:** Entwurf / Planungsphase **Zielarchitektur:** Stack-based Virtual Machine (ähnlich Lua 5.x / Python) ## 1\. Motivation & Architektur-Ziele * **Status Quo:** Der aktuelle AST-Evaluator ist mächtig, flexibel und ideal für Debugging, leidet aber unter "Pointer Chasing" (Cache Misses) und Rekursions-Overhead (CPU Stack Frames). * **Ziel:** Maximale Ausführungsgeschwindigkeit für typisierte, numerische Operationen bei gleichzeitiger Beibehaltung der vollen Sprachflexibilität (Closures, dynamische Typen). * **Strategie:** Implementierung einer linearen Stack-Maschine. * **Compiler:** Transformiert den *spezialisierten* AST in ein flaches Array von Instruktionen. * **VM:** Eine "Dispatch Loop", die Instruktionen abarbeitet und Delphi-Funktionen für komplexe Datentypen (Records, Series) als "Fernsteuerung" nutzt. ----- ## 2\. Phasenplan ### Phase 1: Das Fundament (Datenstrukturen) **Ziel:** Definition der binären Repräsentation des Codes und des Laufzeit-Stacks. * **Task 1.1: Stack-Architektur definieren** * Implementierung von `TStackSlot` als **Tagged Union** (Variant Record). * Größe: Max. 16 Bytes (Alignment-freundlich). * Typen: `skEmpty`, `skInt64`, `skDouble`, `skBoolean`, `skPointer` (für RefCounted Objekte). * **Task 1.2: OpCodes definieren (`TOpCode`)** * Kategorisierung in: Stack Ops, Arithmetik (Getrennt nach `_Int`, `_Flt`, `_Dyn`), Flow Control, Calls. * **Task 1.3: Instruktions-Format (`TInstruction`)** * Record mit `OpCode` (Byte/Enum) und Argumenten (`Arg1`, `Arg2`, `Arg3`: Integer). * **Task 1.4: Container (`TBytecodeChunk`)** * Klasse, die `TArray`, `TArray` (Constant Pool) und Metadaten (MaxStackSize) hält. ### Phase 2: Der Compiler (Core Arithmetic) **Ziel:** Kompilierung einfacher mathematischer Ausdrücke ohne Kontrollfluss. * **Task 2.1: Compiler-Gerüst (`TBytecodeCompiler`)** * Implementierung als `TAstVisitor` (oder `IAstVisitor`). * Verwaltung des `TBytecodeChunk`. * Verwaltung einer virtuellen "Stack Height" zur Berechnung von `MaxStackSize`. * **Task 2.2: Konstanten laden** * Visitor für `VisitConstant`. * Logik: Konstante im Pool suchen/einfügen $\to$ `opLdConst ` emittieren. * **Task 2.3: Arithmetik & Typ-Spezialisierung** * Visitor für `FunctionCall` (Spezialfall: Binäre Operatoren). * Nutzung der `IStaticType`-Informationen aus dem AST. * Entscheidunglogik: * Sind Operanden `Int64`? $\to$ `opAddInt`. * Sind Operanden `Double`? $\to$ `opAddFlt`. * Sonst $\to$ `opAdd` (Fallback). ### Phase 3: Die Virtual Machine (The Engine) **Ziel:** Ausführung des in Phase 2 generierten Codes. * **Task 3.1: Die VM-Klasse (`TVM`)** * Aufbau des `OperandStack` (Array of `TStackSlot`). * Register: `IP` (Instruction Pointer), `SP` (Stack Pointer), `BP` (Base/Frame Pointer). * **Task 3.2: Dispatch Loop** * Implementierung der `Run(Chunk)` Methode. * Großes `case Instruction.OpCode of ...`. * **Task 3.3: Implementierung der Core-OpCodes** * `opLdConst`: Kopieren von Constant-Pool auf Stack. * `opAddInt`: Roher Zugriff auf `Stack[SP].AsInt`. (Performance-kritisch\!). * `opAdd`: Generischer Pfad (Unboxing, Operation, Boxing). ### Phase 4: Variablen & Kontrollfluss **Ziel:** Unterstützung von `if`, lokalen Variablen und einfachen Schleifen (`recur`). * **Task 4.1: Lokale Variablen** * Mapping im Compiler: AST `SlotIndex` $\to$ Stack-Relativ-Index. * OpCodes: `opLdLocal `, `opStLocal `. * **Task 4.2: Sprünge (Jumps)** * Compiler: Handling von `VisitIfExpression`. * Logik: Emittieren von Platzhalter-Jumps, Patching der Sprungziele nach Generierung des Branches. * OpCodes: `opJmp`, `opJmpFalse`. * **Task 4.3: TCO / Recur** * `VisitRecurNode`: Generierung von `Move` Instruktionen (Argumente an Position der Parameter kopieren) + `opJmp` zum Start der Funktion. ### Phase 5: Funktionen & Closures (Die Kür) **Ziel:** First-Class Functions und Upvalue-Handling. * **Task 5.1: Funktions-Prototypen** * Erweiterung `TBytecodeChunk` um Sub-Chunks (Prototypen für innere Funktionen). * **Task 5.2: Upvalue-Analyse Integration** * Nutzung der Ergebnisse des Binders/UpvalueAnalyzers. * Compiler muss wissen, welche Variable Stack-Local ist und welche ein Upvalue ist. * **Task 5.3: Closure-Instanziierung** * OpCode: `opClosure `. * VM: Erzeugt `TClosure` Objekt, sammelt "Capture"-Variablen vom Stack ein (Hoisting) und speichert sie im Closure-Objekt. * **Task 5.4: Calls (`opCall`)** * VM: Stack-Frame Management (Sichern von `BP`, `IP` auf dem Call-Stack). * Umschalten des aktiven Chunks. ### Phase 6: Interop & komplexe Typen **Ziel:** Brückenschlag zur existierenden Delphi-Logik. * **Task 6.1: Native Calls (`opCallNative`)** * Aufruf von RTL-Funktionen via Funktionszeiger. * Konvertierung `TStackSlot` $\leftrightarrow$ Argumente. * **Task 6.2: Records & Series** * OpCodes: `opNewRecord`, `opSeriesAdd`. * VM: Ruft direkt `TScalarRecord.Create` etc. auf. Hier wird keine Logik dupliziert, nur delegiert. ----- ## 3\. Technische Eckpfeiler ### Das Datenmodell (VM Stack) ```pascal type TStackSlot = record case Kind: TDataValueKind of vkOrdinal: (AsInt: Int64); vkFloat: (AsFloat: Double); vkObj: (AsPtr: Pointer); // IInterface / TObject / String end; ``` ### Die Optimierungs-Strategie 1. **Binder/TypeChecker:** Leisten die Vorarbeit (Auflösung von Namen zu Indizes, Typ-Inferenz). 2. **Compiler:** Entscheidet statisch über OpCodes (`ADD_INT` vs `ADD`). 3. **VM:** Führt "blind" und schnell aus. Typprüfungen nur im `_DYN` Pfad oder als Assert. ----- ## 4\. Nächste Schritte (Todo) 1. [ ] Anlegen der Unit `Myc.Bytecode.Types` (Definition OpCodes, Instruction, StackSlot). 2. [ ] Implementierung `TBytecodeCompiler` (Skeleton: Nur Constants & Return). 3. [ ] Implementierung `TVM` (Skeleton: Stack setup, Dispatch loop für Const/Ret). 4. [ ] Erster Integrationstest: `42` kompiliert $\to$ VM führt aus $\to$ Resultat 42. 5. [ ] Erweiterung um `BinaryOp` (Add/Sub) inkl. Typ-Spezialisierung. -----