Implementation and Evaluation of a Safe Runtime in Cyclone Matthew Fluet Cornell University Daniel...

35
Implementation and Evaluation of a Safe Runtime in Cyclone Matthew Fluet Cornell University Daniel Wang Princeton University

Transcript of Implementation and Evaluation of a Safe Runtime in Cyclone Matthew Fluet Cornell University Daniel...

Implementation and Evaluation of a Safe Runtime

in Cyclone

Matthew FluetCornell University

Daniel WangPrinceton University

Introduction

Web-based applications• Written in high-level, safe languages

• C#, Java, Perl, PHP, Python, 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

Safe, C-like language• Static type- and control-flow analysis

Intended for systems programming• Data representation

• Resource management

Region-based memory management• Static, lexical, dynamic, heap, unique, …

Simple Copying Collector

From-space and To-space

Forwarding pointers

Simple Copying Collector

From-space and To-space• Natural correspondence with regions

• LIFO discipline of lexical regions insufficient

• Dynamic regions appear to be sufficient

Forwarding pointers

Dynamic Regions

Non-nested lifetimes Manual creation and deallocation Represented by unique pointer (key)

Unique pointer ≡ Capability• Access the region

Dynamic Regions

Operations• new: create a fresh dynamic region

• Produces unique key

• open: open a dynamic region for allocation• Temporarily consumes key

• free: deallocate a dynamic region• Permanently consumes key

GC and Dynamic Regions

. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .

GC and Dynamic Regions

. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .

GC and Dynamic Regions

. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .

GC and Dynamic Regions

. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .

GC and Dynamic Regions

. . .// create the to-space’s keylet NewDynamicRegion {<`to> to_key} = new_ukey();state_t<`to> = to_state;// open the from-space’s key{ region from_r = open_ukey(from_key); // open the to-space’s key { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } }// free the from-spacefree_ukey(from_key);. . .

Forwarding Pointers

What is the type of a forwarding pointer?

Forwarding Pointers

What is the type of a forwarding pointer?

A pointer to a Value in To-space

Forwarding Pointers

What is the type of a forwarding pointer?

A pointer to a Value in To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space

Forwarding Pointers

What is the type of a forwarding pointer?

A pointer to a Value in To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a Value in To-space’s To-space’s To-space’s To-space’s To-space, whose forwarding pointer is a pointer to a 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 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 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 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 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 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, …

Dynamic Region Sequences

Introduce a new type constructor mapping region names to region names

typedef _::R next_rgn<ρ::R>

Although the region names ρ and next_rgn<ρ> are related, the lifetimes of their corresponding regions are not

Dynamic Region Sequences

Operations• new, open, free: as for dynamic regions

• next: create next_rgn<ρ> from ρ

Dynamic Region Sequences

Operations• next: create next_rgn<ρ> from ρ

Have an infinite supply of region names• next will create a fresh dynamic region key

Need a linear supply of keys• Use Cyclone’s unique pointers

Dynamic Region Sequences

Operations• next: create next_rgn<ρ> from ρ

A dynamic region sequence is a pair• key: a dynamic region key

• gen: a unique pointer Unique pointer ≡ Capability

• Produce the next_rgn<ρ> key and gen

• Consumed by next

Dynamic Region Sequences

Operations• new: create a fresh dynamic region sequence

• Produces unique key and gen

• next: creates next dynamic region sequence• Produces unique key and gen

• Permanently consumes 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 DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}

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 DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}

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 DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}

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 DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}

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 DRSeq{to_key, to_gen} = next_drseq(from_gen); state_t<next_rgn<`r>> to_state; // open the from-space { region from_r = open_ukey(from_key); // open the to-space { region to_r = open_ukey(to_key); // copy the state and reachable data to_state = copy_state(to_r, from_state); } // pack the new gc state gcs = GCState{DRSeq{to_key, to_gen}, to_state}; } // free the from space free_ukey(from_key); return gcs;}

GC and Dynamic Region Sequences

Comparison with type-preserving GCs• Interpreter can be written in a trampoline

style, rather than continuation passing style

• Intuitive typing of forwarding pointers

Performance Evaluation

Interpreter Runtime

Cyclone (Safe GC)

Safe Safe

Cyclone (BDW GC)

Safe Unsafe

SISC (Sun JVM)

Safe Unsafe

MzScheme (BDW GC)

Unsafe Unsafe

Performance Evaluation

Normalized Execution Times

0

0.5

1

1.5

2

tak deriv puzzle fft traverse

Cyclone (Safe GC)

Cyclone (BDW GC)

SISC

MzScheme

Performance Evaluation

Maximum Working Set

0

1000

2000

3000

4000

5000

6000

tak

deriv

puzzle fft

trave

rse

Vir

tual

Pag

es Cyclone (Safe GC)

Cyclone (BDW GC)

SISC

MzScheme

Size of Unsafe Code

Interpreter

(lines of code)

Runtime System

(lines of code)

Cyclone

(Safe GC)0 1800

Cyclone

(BDW GC)0 9000

SISC

(Sun JVM)0 229,100

MzScheme

(BDW GC)31,000 9000

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