The New GHC/Hugs Runtime System
Total Page:16
File Type:pdf, Size:1020Kb
The New GHCHugs Runtime System Simon Marlow Simon Peyton Jones University of Glasgow August Abstract This pap er describ es the new runtime system b eing developed for the Glasgow Haskell Compiler The goal is to provide supp ort for mixed interpretedcompiled execution of Haskell programs with Hugs as the interpreter In the pro cess weve taken the opp or tunity to x some of the deciencies of the old system such as garbage collection of CAFs add some new features costcentre stack proling and a more exible storage manager and improve p erformance one stack instead of two b etter register usage on registerchallenged architectures We also to ok the opp ortunity to design a clean simple API to the runtime system that would allow it to b e used in a variety of applications from standalone Haskell binaries and interactive interpreters to encapsulated COMCORBA ob jects Introduction Compilers get the headlines but b ehind every great compiler lies a great runtime system A surprising amount of work go es into runtime systems but disprop ortionately few pap ers are written ab out them This pap er describ es the design of the runtime system we have built to supp ort mixed compiledinterpreted execution of Haskell Runtime systems start simple after all the compiler translates all the programmerwritten source into executable co de so what is there to do Initially not much p erhaps but serious language implementations rapidly grow features that require runtime supp ort To b e sp ecic the runtime system we describ e in this pap er supp orts the following features Mixed compiledinterpreted execution was our prime goal Section The program mer sees the Hugs interpreter but can load mo dules compiled by the Glasgow Haskell compiler GHC Execution switches b etween compiled and interpreted co de at a rather negrain level The storage manager includes a generational garbage collector Section The storage manager is made more complicated by the need to supp ort a number of language ex tensions namely Mutable variables and arrays supp ort the state monad LJ Weak pointers allow the programmer to build selfcleaning memotables among other things DBE Stable pointers are immutable names for heap ob jects they allow p ointers to Haskell ob jects to b e held outside the heap From the programmers p oint of view a big improvement is that the maximum heap size no longer has to b e sp ecied instead the heap simply grows and shrinks as required Concurrency The runtime system supp orts Concurrent Haskell by default PJGF and hence has to manage multiple Haskell threads Proling is now recognised as even more imp ortant for functional languages than for imp er ative ones We supp ort b oth space and time proling using Jarviss costcentre stacks Jar a development of our earlier work on cost centres SPJ Section The foreign language interface allows C or COMCORBA to call a Haskell function or b e called by a Haskell function Overview The runtime system has three main comp onents see Figure A scheduler which manages the various threads in the system The scheduler sits at the centre of the action every thread returns to the scheduler b efore the next thread is run and the garbage collector is normally called from the scheduler level The scheduler is describ ed in detail in Section The storage manager consists of a lowlevel blo ck allo cator that requests storage on demand from the op erating system and a garbage collector The storage manager is describ ed in Section The interpreter executes bytecodes These may b e read from a le or dump ed directly in the heap by an external bytecode compiler The entire runtime system is a library that can b e embedded in some larger program the client application The ones we have in mind are The Hugs interpreter a standalone GHCcompiled binary a library callable from some enclosing C or Java program a COM or CORBA ob ject Client Appliccation Runtime System Storage Manager Interpreter Block Allocator Scheduler Compiled Haskell Code Figure Runtime System Overview Heap ob jects A central asp ect of the design is the shap e of heapallo cated ob jects In particular since an ob ject might b e allo cated by Hugs and then used by GHCcompiled co de or vice versa Hugs and GHC must agree precisely on the layout of heap ob jects Every heap ob ject lo oks like Figure The rst word of every ob ject is called its info pointer and p oints to the static entry code of that ob ject The entry co de is the co de that evaluates the ob ject to weak head normal form it is the mostused eld during execution as opp osed to garbage collection Immediately b efore the entry co de is the ob jects info table The info table has elds that say what kind of ob ject this is and hence what its layout is this information is required by the garbage collector More sp ecically the elds of an info table are as follows Closure Info Payload Pointer Info Table Code Figure A Closure Closure type a constant indicating which kind of closure this is eg function thunk constructor etc Layout information for the garbage collector either a pair p ointers nonp ointers or a bitmap A p ointer to the SRT for the ob ject see Section Closure ags several ono ags for quick access to certain prop erties of the closure eg is static is p ointed etc Various optional proling parallel and debugging elds 1 A simpler alternative would b e to make the info p ointer p oint to the info table and p oint to the entry co de from an entry in the info table Having the info p ointer p oint directly to the entry co de instead lo oks attractive b ecause it requires one fewer indirections However it p ollutes the instruction cache with neverexecuted info tables and may not b e a win on mo dern architectures We intend to exp eriment with the more conventional layout The runtime system supp orts quite a wide variety of heap ob jects They fall into three main groups 1 Simpler not only b ecause it is more conventional but also b ecause one can only generate this layout if one generates assembly co de directly If one go es via C then one has to p ostpro cess the output co de to achieve the same eect Pointed ob jects represent values of a p ointed type that is a type that includes b ottom All p ointed ob jects may b e evaluated or entered This is done by putting the address of the ob ject in a register and jumping to the ob jects entry co de Pointed ob jects include Thunks unevaluated closures Data constructors Functions Partial applications these arise from an up date of a functionvalued thunk Indirections which are used to overwrite a thunk with its value Black holes which overwrite a thunk when its evaluation is b egun but b efore its value has b een computed Section Unp ointed ob jects represent values of unp ointed type that is a type that do es not include b ottom A p ointer to an unp ointed heap ob ject never p oints to a thunk or an indirection it always p oints to the ob ject itself Examples include Immutable arrays Mutable arrays and variables MVars required for Concurrent Haskell Weak Pairs for supp orting memo tables Administrative ob jects are allo cated by the runtime system itself and never seen by the programmer They include Thread state ob jects TSOs These contain the state of a given Haskell thread including the threads stack Byte co de ob jects BCOs These contain byte co des for the interpreter The stable p ointer table which maps the stable name of an ob ject to its heap address The Storage Manager The runtime system includes a completely rewritten storage manager providing several en hancements b oth for compiled and interpreted execution Hugs in particular will b enet from an industrialstrength garbage collector To summarise the main improvements provided by the new storage manager and garbage collector Dynamic resizing for heap and thread stacks b etter p erformance for programs with low memory requirements and no more heapsize settings The storage manager will also b e able to adjust its memory requirements to optimise the tradeo b etween time and space For example it could reduce the size of the heap if the system is paging excessively The garbage collector will supp ort multiple generations and will even b e able to adjust the number of generations during execution dep ending on the storage requirements of the program It will also allow ob jects to b e aged within a generation by dividing the generation into steps this prevents ob jects b eing promoted to the next generation when they are still very young Toplevel expressions CAFs will b e garbage collected Previously the storage allo c ated by a CAF would b e retained throughout the lifetime of the program The new storage manager will b e able to traverse the co de tree and discover which CAFs are still accessible allowing garbage CAFs to b e collected More ab out this in Section Large ob jects such as arrays and thread stacks can b e treated indep endently by the storage manager allowing them to remain at static lo cations in memory Weak p ointers Using weak p ointers or weak pairs we can provide supp ort for hashed memo tables without space leaks The driving technical decision is to allow the heap to consist of many discontiguous areas rather than a single large continguous address space In fact we go further dividing the heap into blocks of uniform size k bytes at present The heap can then b e partitioned b etween generations and age steps with each generation in a exible and dynamic way The blo cks making up a partition do not need to b e contiguous so it is easy to use any free