Implementation and Evaluation of a Safe Runtime in Cyclone Matthew Fluet
Introduction Web-based applications Application servers 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 Performance Evaluation 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: Regions Region variety Allocation (objects) Deallocation Aliasing (what) (when) Stack static whole region exit of lexical scope unrestricted Lexical dynamic Dynamic manual Heap (`H) single objects automatic (BDW GC) Unique (`U) restricted Ref-counted (`RC)
Cyclone: Regions Region variety Allocation (objects) Deallocation Aliasing (what) (when) Stack static whole region exit of lexical scope unrestricted Lexical dynamic Dynamic manual Heap (`H) single objects automatic (BDW GC) Unique (`U) restricted Ref-counted (`RC)
Cyclone: Regions Region variety Allocation (objects) Deallocation Aliasing (what) (when) Stack static whole region exit of lexical scope unrestricted Lexical dynamic Dynamic manual Heap (`H) single objects automatic (BDW GC) Unique (`U) restricted Ref-counted (`RC)
Cyclone: Regions Region variety Allocation (objects) Deallocation Aliasing (what) (when) Stack static whole region exit of lexical scope unrestricted Lexical dynamic Dynamic manual Heap (`H) single objects automatic (BDW GC) Unique (`U) restricted Ref-counted (`RC)
Cyclone: Regions Region variety Allocation (objects) Deallocation Aliasing (what) (when) Stack static whole region exit of lexical scope unrestricted Lexical dynamic Dynamic manual Heap (`H) single objects automatic (BDW GC) Unique (`U) restricted Ref-counted (`RC)
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); }
Simple Stop-and-Copy Collector
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
Performance Evaluation Interpreter Runtime Cyclone (Safe GC) Safe Cyclone (BDW GC) Unsafe SISC (Sun JVM) MzScheme (BDW GC)
Performance Evaluation
Performance Evaluation
Size of Unsafe Code Interpreter (lines of code) Runtime System Cyclone (Safe GC) 1800 (BDW GC) 9000 SISC (Sun JVM) 229,100 MzScheme 31,000
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