Effiziente Virtuelle Maschinen fr funktionale Programmiersprachen Xavier Leroy
- Slides: 108
Effiziente Virtuelle Maschinen für funktionale Programmiersprachen Xavier Leroy, The ZINC experiment: an economical implementation of the ML language. Technical report 117, INRIA, 1990
Überblick n n Motivation Eigenschaften funktionaler Sprahen ¨ n n Die abstrakte Maschine Naive Auswertung Analyse der Auswertung Echte Mehrfachapplikation ¨ n N-ary / Unary / curried functions Probleme Analyse der Auswertung n n n n n Darstellung von Funktionen Das Instruction Set Die Übersetzungsfunktion Operationale Semantik Unterversorgung Überversorgung Optimierungen Darstellung von Werten Das reale Instruction Set Benchmarks
Motivation n Wie können Programme in funktionalen Sprachen effizient und plattformunabhängig ausgeführt werden ? n native Code Compiler hohe Ausführungsgeschwindigkeit ¨ Programmdarstellung ist plattformabhängig ¨ Compiler müssen für jede Ziel-Plattform neu entwickelt werden ¨ n Virtuelle Maschine VM selbst ist plattformabhängig, aber leicht portierbar ¨ Bytecode ist plattformunabhängig ¨ Overhead der VM kann minimiert werden ¨
Eigenschaften funktionaler Sprachen n Abstraktion ¨ ¨ ¨ n Applikation ¨ ¨ n Curried functions: val f = fn a => fn b => a+b Unary functions: val f = fn (a, b) => a+b N-ary functions ? mit Unterversorgung von Argumenten mit Überversorgung von Argumenten Schleifen werde durch rekursive Funktionen dargestellt.
N-ary functions n n-ary functions sind Funktionen mit mehr als einem Argument. Bei der Ausführung werden diese zurückübersetzt in einfachere Funktionen. Es gibt dazu zwei Möglichkeiten fun f (a b) = a+b n als unary functions mit Argumenten-Tupel fun f (a, b) = a+b n oder als curried functions val f = fn a => fn b => a+b
Vergleich von Unary / curried functions n Nachteil bei Argumenten-Tupel: ¨ n Allokation des Argumenten-Tupel auf dem Heap bei jedem Aufruf Vorteil von curried functions: Curried functions sind bei partieller Anwendung verwendbar: ¨ val add = fn a => fn b => a+b ¨ map (add 5) [1, 2, 3] ¨ n Partielle Applikation ist bei Argumenten-Tupel nicht möglich. => Curried functions sollten effizient implementiert werden! => N-ary functions als curried functions übersetzbar.
Überblick n n Motivation Eigenschaften funktionaler Sprahen ¨ n n Die abstrakte Maschine Naive Auswertung Analyse der Auswertung Echte Mehrfachapplikation ¨ n N-ary / Unary / curried functions Probleme Analyse der Auswertung n n n n n Darstellung von Funktionen Das Instruction Set Die Übersetzungsfunktion Operationale Semantik Unterversorgung Überversorgung Optimierungen Darstellung von Werten Das reale Instruction Set Benchmarks
Die abstrakte Maschine n Die abstrakte Maschine besteht aus folgenden Komponenten: Der Akkumulator enthält Zwischenergebnisse ¨ Der Code-Zeiger zeigt auf die nächste auszuführende Instruktion. ¨ Die Umgebung verwaltet alle aktuellen Bezeichnerbindungen. ¨ Auf dem Stack werden Aufrufparameter, Ergebnis-Werte und Closures von unterbrochenen Auswertungen abgelegt. ¨ n Die Semantik der Maschine wird bestimmt durch: Das Instruction Set der Maschine. ¨ Die Operationale Semantik bestimmt wie diese Instruktionen in Abhängigkeit vom aktuellen Inhalt von Umgebung und Stack ausgewertet werden. ¨
Naive Auswertung n Bei der naiven Auswertung wird jeweils ein Parameter angewandt. n M N 1 N 2 ==> (M N 1) N 2 n Über- und Unterversorgung betrachten wir später!
Auswertungsbeispiel Akkumulator n (fn a => fn b => a + x) 3 x n Um die erste Applikation auszuführen, wird der Folgeausdruck als Closure auf den Stack gelegt. Umgebung x: 7 Stack
Auswertungsbeispiel Akkumulator n (fn a => fn b => a + x) 3 n Der Parameter wird in den Akkumulator geladen. Closure A Umgebung Code x: 7 Stack X Umgebung x: 7 Closure A
Auswertungsbeispiel Akkumulator 3 n (fn a => fn b => a + x) n … und auf den Stack gelegt. Closure A Umgebung Code x: 7 Stack X Umgebung x: 7 Closure A
Auswertungsbeispiel Akkumulator n fn a => fn b => a + x n Die Abstraktion wird ausgeführt, indem das Argument von Stack genommen wird und als „a“ in die Umgebung eingefügt. Closure A Umgebung Code x: 7 Stack X Umgebung x: 7 3 Closure A
Auswertungsbeispiel Akkumulator n fn b => a + x n Bei einer weiteren Abstraktion ist die Auswertung zunächst abgebrochen. Das Zwischenergebnis wird in einer Closure in den Akkumulator gepackt. Closure A Umgebung Code x: 7 X a: 3 Stack Umgebung x: 7 Closure A
Auswertungsbeispiel Akkumulator Closure B n Die neue Closure ersetzt die unterbrochene Auswertung auf dem Stack. Diese wird fortgesetzt. Closure B Closure A Code fn b => a + x X Umgebung x: 7 Stack a: 3 Closure A
Auswertungsbeispiel Akkumulator n x n Das nächste Argument wird in den Akkumulator geladen. Closure B Umgebung Code x: 7 Stack fn b => a + x Umgebung x: 7 a: 3 Closure B
Auswertungsbeispiel Akkumulator 7 n … und auf den Stack gelegt. Die unterbrochene Auswertung wird fortgesetzt. Closure B Umgebung Code x: 7 Stack fn b => a + x Umgebung x: 7 a: 3 Closure B
Auswertungsbeispiel Akkumulator n fn b => a + x n Die Abstraktion wird ausgeführt, indem das Argument von Stack genommen wird und als „b“ in die Umgebung eingefügt. Umgebung Stack x: 7 a: 3 7
Auswertungsbeispiel Akkumulator n a + x n „a“ wird aus der Umgebung in den Akkumulator geladen. Umgebung x: 7 a: 3 b: 7 Stack
Auswertungsbeispiel Akkumulator 3 n + x n … und auf den Stack gelegt. Umgebung x: 7 a: 3 b: 7 Stack
Auswertungsbeispiel Akkumulator n + x n „x“ wird aus der Umgebung in den Akkumulator geladen. Umgebung Stack x: 7 a: 3 b: 7 3
Auswertungsbeispiel Akkumulator 7 n + n Der oberste Wert auf dem Stack wird zum Akkumulator addiert. Umgebung Stack x: 7 a: 3 b: 7 3
Auswertungsbeispiel Akkumulator 10 n Der Wert im Akkumulator ist das Ergebnis. Umgebung x: 7 a: 3 b: 7 Stack
Analyse der Auswertung n Die Auswertung von Mehrfach-Applikationen erfolgt schrittweise: n Bei Left-To-Right Evaluation: ((((M) (N 1)) (N 2)) (N 3)) ¨ Reihenfole: M, N 1, (M N 1)=a, N 2, (a N 2)=b, N 3, (b N 3) ¨ n Bei der Auswertung jeder Applikation [außer der letzten] entsteht eine Closure für das bisher erzeugte Zwischenergebnis. n-Argumente => n-1 Closures.
Probleme dieser Auswertung n Es werden für k Argumente mindestens k - 1 Closures verwendet. n Closures werden auf dem Heap angelegt. Allokationen sind zeitintensiv ¨ Die Closures werden [teilweise] nur einmal verwendet. ¨ Der Speicherbedarf steigt. ¨ Die Garbage Collection wird häufiger verwendet. ¨ n Wie kann man diese Closures meiden ?
Überblick n n Motivation Eigenschaften funktionaler Sprahen ¨ n n Die abstrakte Maschine Naive Auswertung Analyse der Auswertung Echte Mehrfachapplikation ¨ n N-ary / Unary / curried functions Probleme Analyse der Auswertung n n n n n Darstellung von Funktionen Das Instruction Set Die Übersetzungsfunktion Operationale Semantik Unterversorgung Überversorgung Optimierungen Darstellung von Werten Das reale Instruction Set Benchmarks
„Echte“ Mehrfachapplikation - Vorteile n Alle Argumente könnten vor der Applikation auf den Stack gelegt werden. Die Auswertung muss nicht nach jeder Teilapplikation unterbrochen werden. n Die Reihenfolge bei 3 -fach-Applikation M N 1 N 2 N 3 ist: bei Einzelapplikationen: M, N 1, (M N 1)=a, N 2, (a N 2)=b, N 3, (b N 3) ¨ bei Mehrfachapplikation: M, N 1, N 2, N 3, (M N 1 N 2 N 3) ¨ n Die Applikation aller Argumente erzeugt keine unnötigen Closures.
Probleme der Mehrfachapplikation n Mehrere Einzelapplikationen sollten die gleiche Auswertungsreihenfolge haben wie eine Mehrfachapplikation. [Gilt nicht für „Zwischenergebnisse“ !] n Problem: Left-To-Right Evaluation Order M N 1 N 2 => M, N 1, N 2, (M N 1 N 2) ¨ (M N 1) N 2 => [M, N 1, (M N 1)=a], N 2, (a N 2) ¨ n Lösung: Right-To-Left Evaluation Order M N 1 N 2 => N 2, N 1, (M N 1 N 2) ¨ (M N 1) N 2 => N 2, [N 1, (M N 1)=a], (a N 2) ¨
Beispiel für Inkonsistenz n exception Abs exception Right val f = fn x => (raise Abs; fn y => y) n Problem: Left-To-Right Evaluation Order n f 1 (raise Right) => raise Right ¨ ( f 1 ) (raise Right) => raise Abs ¨ n Lösung: Right-To-Left Evaluation Order f 1 (raise Right) => raise Right ¨ ( f 1 ) (raise Right) => raise Right ¨
Auswertungsbeispiel Akkumulator n (fn a => fn b => a + x) 3 x n Zuerst wird das rechte Argument in den Akkumulator geladen. Umgebung x: 7 Stack
Auswertungsbeispiel Akkumulator 7 n (fn a => fn b => a + x) 3 n … und auf den Stack gelegt. Umgebung x: 7 Stack
Auswertungsbeispiel Akkumulator n (fn a => fn b => a + x) 3 n Dann wird das nächste Argument in den Akkumulator geladen. Umgebung Stack x: 7 7
Auswertungsbeispiel Akkumulator 3 n fn a => fn b => a + x n … und auf den Stack gelegt. Umgebung Stack x: 7 7
Auswertungsbeispiel Akkumulator n fn a => fn b => a + x n Die Abstraktion wird ausgeführt, indem das Argument von Stack genommen wird und als „a“ in die Umgebung eingefügt. Umgebung Stack x: 7 3 7
Auswertungsbeispiel Akkumulator n fn b => a + x n Die Abstraktion wird ausgeführt, indem das Argument von Stack genommen wird und als „b“ in die Umgebung eingefügt. Umgebung Stack x: 7 a: 3 7
Auswertungsbeispiel Akkumulator n a + x n „a“ wird aus der Umgebung in den Akkumulator geladen. Umgebung x: 7 a: 3 b: 7 Stack
Auswertungsbeispiel Akkumulator 3 n + x n … und auf den Stack gelegt. Umgebung x: 7 a: 3 b: 7 Stack
Auswertungsbeispiel Akkumulator n + x n „x“ wird aus der Umgebung in den Akkumulator geladen. Umgebung Stack x: 7 a: 3 b: 7 3
Auswertungsbeispiel Akkumulator 7 n + n Der oberste Wert auf dem Stack wird zum Akkumulator addiert. Umgebung Stack x: 7 a: 3 b: 7 3
Auswertungsbeispiel Akkumulator 10 n Der Wert im Akkumulator ist das Ergebnis. Umgebung x: 7 a: 3 b: 7 Stack
Analyse der Auswertung n Bei dieser Auswertung wurden KEINE Closures erzeugt.
Überblick n n Motivation Eigenschaften funktionaler Sprahen ¨ n n Die abstrakte Maschine Naive Auswertung Analyse der Auswertung Echte Mehrfachapplikation ¨ n N-ary / Unary / curried functions Probleme Analyse der Auswertung n n n n n Darstellung von Funktionen Das Instruction Set Die Übersetzungsfunktion Operationale Semantik Unterversorgung Überversorgung Optimierungen Darstellung von Werten Das reale Instruction Set Benchmarks
Darstellung von Funktionen werden durch λ-Abstraktionen mit de-Bruijn-Darstellung ersetzt: val f = fn a => fn b => a + b ¨ val f = λ. λ. <1> + <0> ¨ val f = fn a => fn b => fn x => a + b ¨ val f = λ. λ. λ. <2> + <1> ¨ n Die Bezeichner von neu gebundenen Abstraktionen entfallen. Außerdem reduzieren sich Umgebungen von Funktionen Bezeichner -> Wert auf einfachere Werte-Listen.
Darstellung von Funktionen werden als Werte in Form von Closures dargestellt. Eine Closure besteht aus einer Umgebung und einer Code-Pointer. n Beispiel (ML-Notation): n ¨ val f = fn a => fn b => fn c => a + b ¨ f : {}, o ¨ val g = f 5 3 ¨ g : {a: 5, b: 3}, o
Darstellung von Funktionen werden als Werte in Form von Closures dargestellt. Eine Closure besteht aus einer Umgebung und einer Code-Pointer. n Beispiel (de-Bruijn-Notation): n ¨ val f = λ. λ. λ. <2> + <1> ¨ f : [], o ¨ val g = f 5 3 ¨ g : [3, 5], o
Das Instruction Set n Access(n) - liest das n. Element aus der Umgebung in den Akkumulator. n Reduce(c) - führt c aus und legt den Wert des Akkumulators auf den Stack. n Return - Beendet ein Auswertung eines Ausdrucks n Grab - nimmt das oberste Element [das nächste Argument] vom Stack und fügt sie als neues erstes Element in die Umgebung ein. n Const. Int(i) - legt die Integer-Konstante i in den Akkumulator. n Add. Int - Addiert das oberste Element des Stacks zum Akkumulator.
Die Übersetzungsfunktion [ ] n [ [ [ n Jedes Programm endet mit Return. n n M N ] --> Reduce( [ N ]; Return ); [ M ] <n> ] --> Access(n) λ. N ] --> Grab; [ N ] i ] --> Const. Int(i) N 1 + N 2 ] --> Reduce( [ N 2 ]; Return ); [ N 1 ]; Add. Int
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( [ 2 ]; Return ); [ ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); [ ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( [ ( λ. <0> ) 1 ]; Return ); [ λ. λ. <1> + <0> ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( [ 1 ]; Return ); [ λ. <0> ]; Return ); [ λ. λ. <1> + <0> ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Const. Int(1); Return ); [ λ. <0> ]; Return ); [ λ. λ. <1> + <0> ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Const. Int(1); Return ); Grab; [ <0> ]; Return ); [ λ. λ. <1> + <0> ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Const. Int(1); Return ); Grab; Access(0); Return ); [ λ. λ. <1> + <0> ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Const. Int(1); Return ); Grab; Access(0); Return ); Grab; [ λ. <1> + <0> ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Const. Int(1); Return ); Grab; Access(0); Return ); Grab; [ <1> + <0> ]; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Const. Int(1); Return ); Grab; Access(0); Return ); Grab; Reduce( [ <0> ]; Return ); [ <1> ]; Add. Int; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Const. Int(1); Return ); Grab; Access(0); Return ); Grab; Reduce( Access(0); Return ); [ <1> ]; Add. Int; Return
Übersetzungsbeispiel n ( fn a => fn b => a + b ) ( ( fn x => x ) 1 ) 2 n ( λ. λ. <1> + <0> ) ( ( λ. <0> ) 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Const. Int(1); Return ); Grab; Access(0); Return ); Grab; Reduce( Access(0); Return ); Access(1); Add. Int; Return
Das Instruction Set n Access(n) - liest das n. Element aus der Umgebung in den Akkumulator. n Reduce(c) - führt c aus und legt den Wert des Akkumulators auf den Stack. n Return - Beendet ein Auswertung eines Ausdrucks n Grab - nimmt das oberste Element [das nächste Argument] vom Stack und fügt sie als neues erstes Element in die Umgebung ein. n Const. Int(i) - legt die Integer-Konstante i in den Akkumulator. n Add. Int - Addiert das oberste Element des Stacks zum Akkumulator.
Operationale Semantik Code Akku Env. Stack Code Akku Env Stack Access(k); c a [v 0. . vn] s c vk [v 0. . vn] s Reduce(c‘); c a e s c‘ a e <c, e> : : s Return a e <c 0, e 0> : : s c 0 a e 0 a : : s Return (c 0, e 0) e v : : s c 0 (c 0, e 0) e 0 v : : s Grab; c a e v : : s c a v : : e s Grab; c a e <c 0, e 0> : : s c 0 a e 0 (Grab; c, e) : : s Const. Int(i); c a e s c i e s Add. Int; c a e v : : s c a+v e s Sub. Int; c a e v : : s c a–v e s
Verbleibende Closures n n Closures können nur von Grab und Reduce erzeugt werden. ¨ Grab erzeugt eine Closure genau dann, wenn keine weiteren Argumente vorhanden sind. (Normale Closure) => Das Ergebnis ist eine Abstraktion, die Closure ist notwendig. ¨ Reduce erzeugt Closures, um die Auswertung zu unterbrechen, bis ein Argument reduziert ist. (Markierte Closure) Diese Closures können nicht in die Umgebung eingefügt werden. => Sie können auf dem Stack alloziiert werden. => Sie belasten den Heap / die Garbage Collection nicht. Wie funktioniert Unter- / Überversorgung ?
Überblick n n Motivation Eigenschaften funktionaler Sprahen ¨ n n Die abstrakte Maschine Naive Auswertung Analyse der Auswertung Echte Mehrfachapplikation ¨ n N-ary / Unary / curried functions Probleme Analyse der Auswertung n n n n n Darstellung von Funktionen Das Instruction Set Die Übersetzungsfunktion Operationale Semantik Unterversorgung Überversorgung Optimierungen Darstellung von Werten Das reale Instruction Set Benchmarks
Unterversorgung n Unterversorgung bedeutet, dass eine Curried-Function weniger Argumente bekommt, als sie bekommen könnte. n ( fn a => fn b => 1 ) 2 n ( λ. λ. 1 ) 2 n Reduce( Const. Int(2); Return ); Grab; Access(1); Return
Unterversorgung Akkumulator n Reduce( Const. Int(2); Return ); Grab; Access(1); Return Umgebung Stack
Unterversorgung Akkumulator n Const. Int(2); Return Closure A Umgebung Stack Code Grab; . . . Return Umgebung <Closure A>
Unterversorgung Akkumulator 2 n Return Closure A Umgebung Stack Code Grab; . . . Return Umgebung <Closure A>
Unterversorgung Akkumulator n Grab; Access(1); Return Umgebung Stack 2
Unterversorgung Akkumulator n Grab; Access(1); Return Umgebung 2 Stack
Operationale Semantik Code Akku Env. Stack Code Akku Env Stack Access(k); c a [v 0. . vn] s c vk [v 0. . vn] s Reduce(c‘); c a e s c‘ a e <c, e> : : s Return a e <c 0, e 0> : : s c 0 a e 0 a : : s Return (c 0, e 0) e v : : s c 0 (c 0, e 0) e 0 v : : s Grab; c a e v : : s c a v : : e s Grab; c a e <c 0, e 0> : : s c 0 a e 0 (Grab; c, e) : : s Const. Int(i); c a e s c i e s Add. Int; c a e v : : s c a+v e s Sub. Int; c a e v : : s c a–v e s
Unterversorgung Akkumulator Closure B Umgebung Stack Code Grab; Access(1); Return Umgebung 2 (Closure B)
Überblick n n Motivation Eigenschaften funktionaler Sprahen ¨ n n Die abstrakte Maschine Naive Auswertung Analyse der Auswertung Echte Mehrfachapplikation ¨ n N-ary / Unary / curried functions Probleme Analyse der Auswertung n n n n n Darstellung von Funktionen Das Instruction Set Die Übersetzungsfunktion Operationale Semantik Unterversorgung Überversorgung Optimierungen Darstellung von Werten Das reale Instruction Set Benchmarks
Überversorgung n Überversorgung bedeutet, dass eine Curried-Function mehr Argumente bekommt, als zu erwarten wäre. Daher muss das Ergebnis der Anwendung der erwarteten Argumente eine Abstraktion sein. (Typ-Korrektheit) n ( fn a => a ) ( fn b => 1 ) 2 n ( λ. <0> ) ( λ. 1 ) 2 n Reduce( Const. Int(2); Return ); Reduce( Grab; Const. Int(1); Return ); Grab; Access(0); Return
Überversorgung Akkumulator n Reduce( Const. Int(2); Return ); Reduce( Grab; Const. Int(1); Return ); Grab; Access(0); Return Umgebung Stack
Überversorgung Akkumulator n Const. Int(2); Return Closure A Umgebung Stack Code Reduce. . . ; Return Umgebung <Closure A>
Überversorgung Akkumulator 2 n Return Closure A Umgebung Stack Code Reduce. . . Return Umgebung <Closure A>
Überversorgung Akkumulator n Reduce( Grab; Const. Int(1); Return ); Grab; Access(0); Return Umgebung Stack 2
Überversorgung Akkumulator n Grab; Const. Int(1); Return Closure B Umgebung Stack Code Grab; . . . ; Return Umgebung <Closure B> 2
Operationale Semantik Code Akku Env. Stack Code Akku Env Stack Access(k); c a [v 0. . vn] s c vk [v 0. . vn] s Reduce(c‘); c a e s c‘ a e <c, e> : : s Return a e <c 0, e 0> : : s c 0 a e 0 a : : s Return (c 0, e 0) e v : : s c 0 (c 0, e 0) e 0 v : : s Grab; c a e v : : s c a v : : e s Grab; c a e <c 0, e 0> : : s c 0 a e 0 (Grab; c, e) : : s Const. Int(i); c a e s c i e s Add. Int; c a e v : : s c a+v e s Sub. Int; c a e v : : s c a–v e s
Überversorgung Akkumulator n Grab; Access(0); Return Closure C Umgebung Stack Code Grab; . . . ; Return Umgebung (Closure C) 2
Überversorgung Akkumulator n Access(0); Return Closure C Umgebung Code (Closure C) Stack Grab; . . . ; Return Umgebung 2
Überversorgung Akkumulator (Closure C) n Return Closure C Umgebung Code (Closure C) Stack Grab; . . . ; Return Umgebung 2
Operationale Semantik Code Akku Env. Stack Code Akku Env Stack Access(k); c a [v 0. . vn] s c vk [v 0. . vn] s Reduce(c‘); c a e s c‘ a e <c, e> : : s Return a e <c 0, e 0> : : s c 0 a e 0 a : : s Return (c 0, e 0) e v : : s c 0 (c 0, e 0) e 0 v : : s Grab; c a e v : : s c a v : : e s Grab; c a e <c 0, e 0> : : s c 0 a e 0 (Grab; c, e) : : s Const. Int(i); c a e s c i e s Add. Int; c a e v : : s c a+v e s Sub. Int; c a e v : : s c a–v e s
Überversorgung Akkumulator n Grab; Const. Int(1); Return Umgebung Stack 2
Überversorgung Akkumulator n Const. Int(1); Return Umgebung 2 Stack
Überversorgung Akkumulator 1 n Return Umgebung 2 Stack
Überversorgung Akkumulator Umgebung Stack 1
Weitere Optimierungen n Durch einen Cache (in Registern der Virtuellen Maschine) wird der Zugriff auf die aktuellsten Elemente der Umgebung beschleunigt. n Es gibt spezialisierte Instruktionen für häufige Operationen. (z. B. : Let, Konstante Konstruktoren, Endrekursion …) n Durch eine globale Variablenliste wird die Umgebung stark verkleinert. n Trennung von Argumenten-Stack und Return-Stack
Überblick n n Motivation Eigenschaften funktionaler Sprahen ¨ n n Die abstrakte Maschine Naive Auswertung Analyse der Auswertung Echte Mehrfachapplikation ¨ n N-ary / Unary / curried functions Probleme Analyse der Auswertung n n n n n Darstellung von Funktionen Das Instruction Set Die Übersetzungsfunktion Operationale Semantik Unterversorgung Überversorgung Optimierungen Darstellung von Werten Das reale Instruction Set Benchmarks
Darstellung von Werten 31 -bit Integer . . 1 32 -bit Pointer . . 00 ? Real . . 10 n Alle Werte sind 32 -bit Worte. n unboxed, also direkt, werden folgende Typen abgelegt: 31 -bit vorzeichenbehaftete Integer werden als 32 -bit Integer mit gesetztem Bit 0 dargestellt. ¨ Zeiger in den Heap (oder in den Code auf Konstanten) werden direkt abgelegt. (Ihre Binärdarstellung endet auf 00. ) ¨ n Alle anderen Datentypen werden im Heap angelegt und es wird nur der Zeiger auf diesen Speicherblock abgelegt. „boxed“
Heap-Aufbau n Der Speicher besteht aus 32 -bit Worten, die in Blöcke aufgeteilt werden. Jeder Block hat einen Header, mit einer Beschreibung seines Inhalts, seiner Größe und 2 Bits für die Garbage Collection. n Die Garbage Collection kann selbständig zwischen unstrukturierten Daten und Listen von Werten unterscheiden. n Es gibt im Code keine Zeiger in den Heap. Es gibt in der globalen Variablenliste Zeiger in den Heap. n
Speicherblöcke im Heap n n Im ersten Word eines Blocks steht: n – die Größe des Blocks (22 bit) GC – Daten für den Garbage Collector (2 bit) tag – Typinformation (8 bit) n GC tag field 1. . . fieldn n n Das Tag-Feld bestimmt die Interpretation des Inhalts tag=255: Unstrukturierte Blöcke tag=254: Closure tag<254: Konkreter Datentyp
Unstrukturierte Blöcke n Unstrukturierte Blöcke enthalten keine Werte. tag = 255 n Beispiel: Strings n 5 GC Abst ract _Mas n Strings werden nullterminiert abgelegt Sie werden aufgefüllt, so dass Länge = 4 * Block-Größe – letztes Byte. n Beispiel: var x = „Abstract_Maschine“ n n chin e 3 255
Closure n n Closures sind stukturierte Blöcke, d. h. sie enthalten Werte. tag = 254 k+1 GC <codepointer> value 1 n n 254 Der Datenblock besteht aus dem Codezeiger und der zugehörigen Umgebung value 2 Im Beispiel: k Elemente in der Umgebung valuek …
Konkrete Datentypen n n Instanzen sind strukturierte Blöcke, d. h. sie enthalten Werte. tag < 254 2 GC 0 value 1 value 2 n n Beispiel: datatype t = I of int * int | S of string 1 Varianten werden beginnend mit 0 durchnummeriert. Die Variantennummer wird als tag verwendet. GC pointer 1 1
Konkrete Datentypen (2) n Sind mehr als 254 Varianten vorhanden, so muss eine alternative Darstellung verwendet werden. 2 GC 0 0 value 1 n n Die Variantennummer wird als Integer im ersten Daten-Feld abgelegt. Beispiel: datatype t = C 0 of int |. . . | C 254 of int * int 3 GC 254 value 1 value 2 0
Beispiel n n datatype t = A of int | B of int * string * (int->int) val x = B(3, A 2, „test“, (fn a => fn b => a+b) 3) 1 GC 0 2 4 GC 3 1 2 GC 255 2 GC o test o o 4 3 o 254
Vorteile der Blockdarstellung n Der Garbage Collector kann erkennen, ob es sich um reine Daten oder eine Liste von Werten handelt, die Zeiger enthalten können. n Zur Erinnerung: Zeiger können von Integern an den beiden abschließenden 00 unterschieden werden.
Überblick n n Motivation Eigenschaften funktionaler Sprahen ¨ n n Die abstrakte Maschine Naive Auswertung Analyse der Auswertung Echte Mehrfachapplikation ¨ n N-ary / Unary / curried functions Probleme Analyse der Auswertung n n n n n Darstellung von Funktionen Das Instruction Set Die Übersetzungsfunktion Operationale Semantik Unterversorgung Überversorgung Optimierungen Darstellung von Werten Das reale Instruction Set Benchmarks
Das reale Instruction Set n n n n n Constants and literals Function handling Environment handling Building and destructing blocks Integers Floating-point numbers Strings Predicates Branches and conditional branches Miscellaneous
Constants and literals n Constbyte(int 8), Constshort(int 16), Constlog(int 32) Lädt eine Konstante. n Atom(tag), Atom 0, …, Atom 9 Lädt einen Pointer auf einen konstanten Block mit Tag tag. n Get. Global(int 16), Set. Global(int 16) Lädt eine globale Variable oder speichert diese.
Function handling n Push, Pushmark Legt den Akkumulator bzw. eine Markierung auf den Stack n Apply, App. Term Führt die Closure im Akkumulator aus. (Normal / endrekursiv) n Return Beendet die Auswertung eines Ausdrucks n Grab Fügt ein Argument vom Stack in die Umgebung ein. n Cur(ofs) Erstellt eine Closure für Codepointer ofs im Akkumulator
Integers and floating-point numbers n Succ. Int, Pred. Int, Neg. Int, Add. Int, Sub. Int, Mul. Int, Div. Int, Mod. Int, And. Int, Or. Int, Xor. Int, Shift. Left. Int, Shift. Right. Int Berechnet die jeweilige Operation mit dem Akkumulator und ggf. dem obersten Element des Stacks. n Float. Of. Int, Int. Of. Float Konvertiert Integer in Fließkommazahlen oder umgekehrt. n Floatop(Add. Float), Floatop(Sub. Float), Floatop(Mul. Float), Floatop(Div. Float) Berechnet die jeweiligen Operationen
Branches and conditional branches n Branchifeqtag(tag, ofs), Branchifneqtag(tag, ofs) Springt relativ um ofs, falls der Akkumulator auf Tag tag zeigt. n Switch(ofs 0, . . . , ofsk) Springt relativ um ofstag falls der Akkumulator auf Tag tag zeigt. n Branchif. Eq(ofs) Springt relativ um ofs, falls der Akkumulator und der oberste Element des Stacks pointer-gleich sind. n Branchif. Equal(ofs) Springt relativ um ofs, falls der Akkumulator und der oberste Element des Stacks struktuell gleich sind. n … viele weitere
Benchmarks n fun fib n = if n<2 then 1 else fib(n-1) + fib(n-2) n fun tak x y z = if x>y then tak (x-1) y z) (tak (y-1) z x) (tak (z-1) x y) else z n fun sum [] = 0 | sum (a: : ar) = a + sum ar fun interval n = if n = 0 then nil else n : : interval(n-1) n fun double f x = f (f x) val quad = double val oct = quad n fun succ n = n+1 n fib 26 tak 18 12 6 sum (interval 10000) double oct (fn x => x+1) 1 map (quad succ) (intervall 1000)
Benchmarks (2)
Quellen n Xavier Leroy, The ZINC experiment: an economical implementation of the ML language. Technical report 117, INRIA, 1990
- Effizientes portfolio
- Hs fulda ai
- Funktionale abhängigkeit
- Funktionale vs objektorientierte programmierung
- Funktionale währung
- Funktionale abhängigkeit
- Funktionale programmierung tu dortmund
- Programmierung
- Maschinen stillstandsgründe
- Manipulation von schutzeinrichtungen rechtliche folgen
- Frequenztechnik
- Funktionselemente von maschinen klasse 6
- Funktionsorgane von maschinen
- Funktionselemente von maschinen
- Photo de marin fils de nolwenn leroy
- Fons leroy
- Leroy impressionismo
- Leroy banda
- Cpia 5 milano
- John atanasoff
- Anémomètre leroy merlin
- Fornecedor leroy merlin
- Signaltique
- Dissection virtuelle souris
- Identitte
- Réalité virtuelle
- Virtuelle friedhöfe
- école virtuelle
- Salle de pilotage
- Calibre logiciel
- Drehteile auftragsvergabe
- Virtuelle adresse in physikalische umrechnen
- Visiter le phare de cordouan
- Fullrate reklame
- Virtuelles unternehmen beispiel
- Verformungsfigur
- Réalité virtuelle
- Dachau visite virtuelle
- The mark ettie character analysis
- Xavier fernando ryerson
- Escola estadual joelina de almeida xavier
- Xavier nicolau
- Bor-yuh evan chang
- Manuela xavier processos
- Xavier barberis
- Mary of guise family tree
- Xavier collilieux
- Henri-françois-xavier de belsunce de castelmoron
- Xavier barberis
- Xavier morandi
- Nascestes no lar que precisavas
- Xavier seiso
- Linear polarization
- Hostilio xavier ratton neto
- Xavier bonilla
- Xavier van rooyen
- Xavier assfeld
- François xavier saluden
- Naviance xavier high school
- Xavier mail delivery robot
- Xavier jeannin
- Francisco xavier medium
- Hannah xavier
- Xavier gabilly
- Xavier amaro
- Lleiva
- Rafael de vasconcelos xavier ferreira
- Xavier naidoo rausammy naidoo
- Minera san xavier
- Xavier fernando
- Xavier zanchi
- Absorbancia
- Xavier barberis
- Mr xavier mystery claim evidence reasoning
- Oskar backlund
- Mr xavier mystery claim evidence reasoning
- Who killed mr xavier answer
- Xavier monnet
- Xavier gimeno
- Se eu morrer antes de você
- Agrg
- Xavier pansaers
- Xavier lachazette
- Xavier leyronas
- Xavier coget
- ética kantiana características
- Xavier landes
- Jacques delors marie lephaille
- Parábola dos talentos emmanuel
- Xavier messeguer
- Chico xavier saudade
- Xavier messeguer
- Xavier calmet
- Inurl:"responsible disclosure"