Evaluation of a Safe

quicksandwalleyeInternet and Web Development

Oct 31, 2013 (4 years and 7 days ago)

103 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


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: Regions

Region variety

Allocation

(objects)

Deallocation

Aliasing

(objects)

(what)

(when)

Stack

static

whole region

exit of

lexical scope

unrestricted

Lexical

dynamic

Dynamic

manual

Heap (
`H
)

single objects

automatic
(BDW GC)

Unique (
`U
)

manual

restricted

Ref
-
counted
(
`RC
)

Cyclone: Regions

Region variety

Allocation

(objects)

Deallocation

Aliasing

(objects)

(what)

(when)

Stack

static

whole region

exit of

lexical scope

unrestricted

Lexical

dynamic

Dynamic

manual

Heap (
`H
)

single objects

automatic
(BDW GC)

Unique (
`U
)

manual

restricted

Ref
-
counted
(
`RC
)

Cyclone: Regions

Region variety

Allocation

(objects)

Deallocation

Aliasing

(objects)

(what)

(when)

Stack

static

whole region

exit of

lexical scope

unrestricted

Lexical

dynamic

Dynamic

manual

Heap (
`H
)

single objects

automatic
(BDW GC)

Unique (
`U
)

manual

restricted

Ref
-
counted
(
`RC
)

Cyclone: Regions

Region variety

Allocation

(objects)

Deallocation

Aliasing

(objects)

(what)

(when)

Stack

static

whole region

exit of

lexical scope

unrestricted

Lexical

dynamic

Dynamic

manual

Heap (
`H
)

single objects

automatic
(BDW GC)

Unique (
`U
)

manual

restricted

Ref
-
counted
(
`RC
)

Cyclone: Regions

Region variety

Allocation

(objects)

Deallocation

Aliasing

(objects)

(what)

(when)

Stack

static

whole region

exit of

lexical scope

unrestricted

Lexical

dynamic

Dynamic

manual

Heap (
`H
)

single objects

automatic
(BDW GC)

Unique (
`U
)

manual

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 poi nter i s a pointer to a
struct Value

i n
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 forwar ding 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
-
spac
e



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

Safe

Cyclone

(BDW GC)

Safe

Unsafe

SISC

(Sun JVM)

Safe

Unsafe

MzScheme

(BDW GC)

Unsafe

Unsafe

Performance Evaluation

Performance Evaluation

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