210 likes | 414 Views
André Santos / Monique Monteiro {alms,mlbm}@cin.ufpe.br. Integrating Haskell to .NET. Rotor Workshop Sep 2005 - MSR. Motivation. Advantages of having Haskell compiler for the .NET platform Easier interop with other languages Stronger integration of Haskell to .NET components and tools
E N D
André Santos / Monique Monteiro {alms,mlbm}@cin.ufpe.br Integrating Haskell to .NET Rotor Workshop Sep 2005 - MSR
Motivation • Advantages of having Haskell compiler for the .NET platform • Easier interop with other languages • Stronger integration of Haskell to .NET components and tools • Performance • Limitation of previous implementations
Related work • Previous Haskell implementations for .NET • Little or no documentation • Partial implementations • (very) limited availability and documentation • Implementation of other functional languages for .NET • Scheme, F#, SML.NET, Mondrian, etc. • But Haskell is a lazy functional language • Implementations of Haskell for the JVM
JVM x .NET CLR JVM ● ○ ○ ○ CLR ○ ● ● ● Focus on OO Languages Focus on language interoperability Support for tail calls Support for function pointers
Main Design Decisions • Evaluation strategy • uses push/enter model (instead of eval/apply) • Data types representation • Use common container classes (instead ofClasses for each constructor of each Haskell datatype) • Closure representation
Closure Representation • One class per closure • Large number of classes: (expected) high overhead for class loading, verification routines, etc. • Classes with Function Pointers • Unverifiable code • Delegates • Type-safe • Better performance in .NET 2.0
One class / closure public class Closure_302 : Closure { public Closure value; public static Closure enter(){ // if value is available // return it // otherwise evaluate specific closure code, update it and return it } }
Common closure class public class Closure : Delegate { public Closure value; public static IClosure Enter(){ // if value is available return it // otherwise save stacks’ state, evaluate (call to Delegate.Invoke), // update value, restore stacks’ state and return value ... } }
Closure Representation • Updateable closures • Keep a value field • Non-updateable closures • Keep an arity field • Keep a partial application field to encapsulate received arguments • Both keep the free variables • Set to null after update • Delegates point to the slow entry point • Slow entry point X fast entry point
Example: map function map = {} \n {f,l} -> case l of Nil {} -> Nil {} Cons {x,xs} -> let fx = {f,x} \u {} -> f {x} fxs = {f,xs} \u {} -> map {f,xs} in Cons {fx,fxs}
Example: generated code public static IClosure map(NonUpdatable clo){ ... } public static IClosure map(IClosure f,IClosure l){ Pack scrutinee = (Pack)l.Enter(); switch(scrutinee.tag){ case 1: return new Pack(1); case 2: Pack_2<IClosure,IClosure> cons = (Pack_2<IClosure,IClosure>)scrutinee; IClosure x = cons.arg1; IClosure xs = cons.arg2; Updateable_2_FV fx_closure = new Updateable_2_FV(fx); fx_closure.fv1 = f; fx_closure.fv2 = x; Updateable_2_FV mfxs_closure = new Updateable_2_FV(mfxs); mfxs_closure.fv1 = f; mfxs_closure.fv2 = xs; return new Pack_2<IClosure,IClosure>(2, fx_closure, mfxs_closure); } } Slow entry point Fast entry point Nil tag Cons tag
Implementation Decisions • Use existing optimizing compiler for Haskell • The Glasgow Haskell Compiler –GHC • STG Intermediate representation Language • Generate code in CIL • No support for explicit tail-calls from C# • Cannot extend (Multicast)delegate class from C#
Current Status • Support for parts of the Haskell prelude • (GHC) modules Base, List, Num, Show, Real, Enum, … • Currently performing tests and performance evaluation using some programs from Nofib Benchmark suite • Limited performance results so far
Execution Times CAFs (top-level constants)
Some Profiling Results • CAFs (updateable closure + value) lead to long-lived objects (Gen 2) and large memory consumption • Delegates are the largest objects • Delegate constructors have the highest cost among runtime system methods
Main Difficulties • In-place updating is not supported • It is not possible to store pointers to references • Tail-calls • It’s not clear in which situations they are supported by the execution system • Delegates? Virtual methods? Method in other assemblies? • “Disabled in fully-trusted environments”
Main Difficulties • CLR stack limitations: • Push/enter approach requires the direct management of a stack for handling calls to unknown functions • Separate stack(s) had to be implemented • Possible solution: eval/apply approach
Main Difficulties • .NET 2.0 in Beta version • Limited profiling tools for .NET 2.0 • Rotor for .NET 2.0 is not available yet • Calls to C routines in Prelude modules • implement .NET FFI convention
Next Steps • Fix the CAF problem • Evaluate changes in delegates inheritance • Investigate tail-calls and their limitations/overhead in .NET 2.0 • Extend Rotor with support for Closures • Investigate ways of exposing Haskell code to other .NET languages and vice-versa
André Santos / Monique Monteiro {alms,mlbm}@cin.ufpe.br Questions?