Redesign of the Oz Compiler Av Markus Bohlin och Lars Bruce
Översikt presentation Introduktion Oz och Mozart Design Mellankodsformat i kompilatorn Registerallokering Kodemission Framtida arbete Slutsatser
Varför en ny kompilator? Originalkompilatorn är mycket effektiv, men… Kompilering sker per definition vilket försvårar modifiering av kompilatorn Den gamla kompilatorn saknar designdokumentation samt är mycket sparsamt kommenterad Utökning av kompilatorn är planerad i framtida projekt Kunskapen om kompilatorn fanns tidigare i Tyskland
Mål med examensarbetet Förståelse för hur kompilatorn fungerar Ny design av kompilatorn på ett öppet, modulärt sätt så att det går lätt att utöka kompilatorn med ny funktionalitet Implementation av den nya kompilatorn I mån av tid: undersök nya analys- och optimeringsmöjligheter
Historien om Oz Utvecklades vid DFKI i Saarbrücken Oz 1 bygger på AKL som utvecklades på SICS Nuvarande version är Oz 3/Mozart Utvecklingen sker numer främst inom DSL på SICS
Språket Oz Dynamiskt typat Automatisk minneshantering Felhantering via undantag Logiska varibler Entiteter med tillstånd, Celler, atomär uppdatering Multiparadigmspråk
Villkorsprogrammering Villkor över ändliga mängder Programmerbara sökstrategier Funktionellt Ivrig och lat evaluering Alla entiteter i språket är första klassens objekt Ej rent funktionellt, har sidoeffekter Multitrådat med dataflödes synkronisering Rättvis schemaläggning, avbrytbara trådar Ultralättviktiga trådar Objektorienterat Multipelt arv
Oz Core language En delmängd av Oz Innehåller ej, t.ex., villkors programmering och objektorientering Alla regelrätta Oz program kan uttryckas i Oz Core language
Mozart Ett mjukvarusystem som implementerar Oz VM och utvecklingsmiljö med kompilator, debug- och monitorerings-verktyg Distribution Transparent Kontroll över distributionen Windows 95/NT och flera UNIX-dialekter
Mozart Virtual Machine - MVM Baseras på Warren Abstract Machine Registermaskin Består av: Motor Schemaläggare Garbage Collector Store – variabelsystem Kan ladda sub-system dynamiskt, t.ex. distribution
Register i MVM Tre typer: X-register Liknar vanliga register Används för parameteröverföring Förstörs i samband med procedur anrop 4096 st. i normala konfigurationen Y-register Påminner om stacken i C Förstörs inte vid procedur anrop G-register Referenser till icke-lokala variabler
Proceduranrop X-register i används för parameter i. För ett anrop till en procedur med ariteten n, används alltså x(0)...x(n-1). Går inte att veta vilka X-register som förstörs av den anropade proceduren – spara alla till Y-register. Inbyggda procedurer i MVM Vanligt förekommande procedurer, t.ex. aritmetiska Laddas in när systemet startar Kompilatorn bestämmer vilka X-register som ska användas Det är känt vilka argument som förstörs.
Design av back-end i originalkompilatorn
Mål med en ny design Övergripande mål: Lätt att modifiera kompilatorn Oberoende moduler / faser Rent gränssnitt mellan faserna Datautbyte mellan faser via mellankodsformat
Design av back-end i den nya kompilatorn
Översättning till mellankodsformat Sista steget i front-end delen av kompilatorn Varför? Ett kodformat som underlättar analys och optimering i back-end Underlättar modularisering av back-end Gör det möjligt att använda samma front- end till flera målmaskiner och samma back- end till flera språk
Fördelen med ett mellankodsformat
Abstrakta instruktioner Bygger mycket på det tidigare mellankodsformatet – virtuella instruktioner En abstrakt instruktion är en högnivåversion av en, eller flera, maskininstruktioner Förändras för varje pass i back-end Saknar hoppinstruktioner, använder istället direkta referenser Ett program uttrycks som en graf bestående av abstrakta instruktioner – enkel att traversera
Kod struktur
Omvandling I front-end representeras programmet av en objektgraf En klass för varje typ av Oz-sats Varje klass har en metod som översätter satsen till abstrakta instruktioner Variabelnamn ersätts med virtuella register Vi spenderade mycket tid på att förstå denna del!
Registerallokering Registerallokering = tilldelning av register till variabler Mål med registerallokering: Generellt: Minska exekveringstid För MVM: Nödvändigt, eftersom MVM är registerbaserad Minimera omgruppering av register Minska användning av Y-register.
Registerallokering för MVM Registerallokering arbetar primärt med X- register Dessa behöver inte allokeras Speciella egenskaper i MVM: Stor mängd X-register Alla registertyper accessas lika snabbt Y-register tar tid att allokera Procedur- och builtin-anrop förstör X-register Parametrar passas i X-register Standardtekniker passar inte bra för MVM
Livenessanalys för MVM Grundläggande analys för att kunna utföra optimeringar När måste vi ha en variabel i ett register? Utförs på virtuella register Vi har valt en enkel strategi: två linjära pass Hitta initieringar Hitta sista accesserna Liveness representeras i en abstrakt instruktion av en bit per virtuellt register
Registerallokering i den nya kompilatorn Endast variabler som är aktiva hålls i register Look-ahead försöker avgöra vad en variabel används för Om en variabel används som argument, försöker man allokera rätt X-register på en gång Hantering av svårigheter Förgreningar, builtins, speciella MVM-instruktioner …
Slutsatser registerallokering Reguljära tekniker är av begränsat intresse Gamla registerallokeringen är bättre Fördröjda allokeringar (mycket effektivt) Instruktioner som initierar lokala variabler flyttas tills just innan de behövs Problemet skjuts upp, vi kan bestämma register senare! Integrerad i registerallokatorn, bör ligga i ett separat pass Stark koppling till övriga delar Nya tekniker behövs!
Översättning till bytekod ”Emitting code” Abstrakta instruktioner till relativa bytekodsinstruktioner Alla referenser i den abstrakta koden ersätts med hopp-instruktioner till symboliska adresser
Peephole optimering Lokal optimering - analyserar och optimerar endast några få instruktioner, ibland endast en, åt gången Fyra typer: Eliminering av onåbar kod Instruktionskombinering Svansanrop, extra viktigt vid svansrekursion Eliminering av onödiga hoppinstruktioner Hopp till hopp Hopp till retursatser
Sista stegen Ersätter de symboliska adresserna med den verkliga Översätter instruktioner till OP-koder Körbart program! Sparas till fil Exekveras direkt i en egen tråd (om den interaktiva kompilatorn används)
Framtida utökningar Bättre GC kräver stöd i kompilatorn Registerallokering Fördröjda allokeringar Analys av registerutnyttjande i procedurer Adaptiv parameteröverföring Sökningstekniker för registerallokering Optimeringar Finns en uppsjö värda att testa i litteraturen
Slutsatser Kompilatorns back-end har modulariserats på ett bra sätt Implementationen är förberedd för utbyggnad Registerallokeringen behöver omkonstrueras Kompilatorn själv kan optimeras