320 likes | 457 Views
Implementation and Evaluation of a Safe Runtime in Cyclone. Matthew Fluet. Introduction. Web-based applications Written in high-level, safe languages C#, Java, Perl, PHP, Phython, Tcl Automatic memory management Application servers Written in unsafe languages
E N D
Implementation and Evaluation of a Safe Runtime in Cyclone Matthew Fluet
Introduction • Web-based applications • Written in high-level, safe languages • C#, Java, Perl, PHP, Phython, Tcl • Automatic memory management • Application servers • Written in unsafe languages • Host applications via interpreters (written in C)
Introduction • Long-term goal: a complete web-application server written in a safe language • Short-term goal: a complete interpreter written in a safe language • Implementing the core of an interpreter is not in itself a significant challenge • Implementing the runtime system is a challenge
Outline • A Scheme interpreter in Cyclone • Why Scheme • Key Features of Cyclone • Core Scheme Interpreter • Garbage Collector • Performance Evaluation • Conclusion
Why Scheme? • Ease of implementation • Core interpreter loop is only ~500 lines • Rely on an external Scheme front-end to expand the full Scheme language into a core Scheme subset • Features desirable for web programming
Key Features of Cyclone • Pointers • Nullable: t* • Non-null: t*@notnull • Fat: t*@fat • Regions • Region names: `r • Pointers: t*`r • Polymorphism: <`r::R>
Cyclone: Dynamic Regions typedef struct DReg<`r>*@notnull`U uregion_key_t<`r::R> struct NewDReg { <`r::R> uregion_key_t<`r> key; } struct NewDReg new_ukey(); void free_ukey(uregion_key_t<`r> k); { region r = open(k); . . . }
Core Scheme Interpreter • Simplified expression language • Variables given as deBruijn indices • Values – heap allocated data • Small-step operational semantics: <H,S,ρ,r> → <H’,S’,ρ’,r’>
Core Scheme Interpreter: Values struct Value<`r::R>; typedef struct Value<`r>*`r value_t<`r::R>; datatype ValueD<`r> { Const_v(const_t<`r> K); Primop_v(primop_t p); Closure_v(unsigned int n, env_t<`r> rho, exp_t<`r> e); Vector_v(value_t<`r>*@fat`r ls); }; struct Value<`r::R> { datatype ValueD<`r> value; };
Heap Allocated Interpreter void scheme(exp_t<`r> prog<`r>(region_t<`r>)) { // load the program into the Cyclone heap exp_t<`H> e = prog(heap_region); // load the initial environment env_t<`H> env = initial_env(heap_region); // construct the initial state state_t<`H> state = State{NULL,env,{.expr = e}}; // take an unbounded number of steps bool done = stepi(-1,heap_region,&state); }
GC and Regions • Separation of From-space and To-space suggests a natural correspondence with Cyclone’s regions • LIFO discipline of lexical regions insufficient • Dynamic regions appear to be sufficient
GC in Spirit . . . // create the to-space’s key let NewDynamicRegion {<`to> to_key} = new_ukey(); state_t<`to> = to_state; // open the from-space’s key { region from_r = open(from_key) // open the to-space’s key { region to_r = open(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } } // free the from-space free_ukey(from_key); . . .
GC and Forwarding Pointers • What is the type of a forwarding pointer?
GC and Forwarding Pointers • What is the type of a forwarding pointer? • A pointer to a struct Value in To-space
GC and Forwarding Pointers • What is the type of a forwarding pointer? • A pointer to a struct Value in To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space
GC and Forwarding Pointers • What is the type of a forwarding pointer? • A pointer to a struct Value in To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a struct Value in To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space’s To-space …
Dynamic Region Sequences • Need a name for all the unwindings • Type constructor mapping region names to region names typedef _::R next_rgn<`r::R> • Forwarding pointers value_t<next_rgn<`r>> • Although the region names`r and next_rgn<`r> are related, the lifetimes of their corresponding regions are not.
Dynamic Region Sequences • Have an infinite supply of region names • Need to ensure an infinite linear supply • Use Cyclone’s unique pointers struct DRGen<`r::R>; typedef struct DRGen<`r>*@notnull`U uregion_gen_t<`r>;
Dynamic Region Sequences struct DRSeq<`r> { uregion_key_t<`r> key; uregion_gen_t<`r> gen; } typedef struct DRSeq<`r> drseq_t<`r>; struct NewDRSeq { <`r::R> drseq_t<`r> drseq; } struct NewDRSeq new_drseq(); drseq_t<next_rgn<`r>> next_drseq(uregion_gen_t<`r> gen);
GC and Dynamic Region Sequences gcstate_t doGC(gcstate_t gcs) { // unpack the gc state let GCState{<`r> DRSeq {from_key, from_gen}, from_state} = gcs; // generate the to-space let DRS{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; { region from_r = open(from_key); { region to_r = open(to_key); to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRS{to_key, to_gen}, to_state}; } free_ukey(from_key); return gcs; }
GC and Dynamic Region Sequesces • Comparison with type-preserving GCs • Interpreter can be written in a trampoline, rather than continuation passing, style • Intuitive typing of forwarding pointers
Conclusion • Significantly reduce amount of unsafe code needed to implement an interpreter • May incur a performance penalty for extra degree of safety • Future Work • Reduce performance penalty • Per thread regions providing customization