Bounding Data Races in Space and Time KC Sivaramakrishnan - - PowerPoint PPT Presentation

bounding data races in space and time
SMART_READER_LITE
LIVE PREVIEW

Bounding Data Races in Space and Time KC Sivaramakrishnan - - PowerPoint PPT Presentation

Bounding Data Races in Space and Time KC Sivaramakrishnan University of Darwin College, 1851 Royal OCaml Labs Cambridge Cambridge Commission 1 Multicore OCaml 2 Multicore OCaml OCaml is an industrial-strength, functional


slide-1
SLIDE 1

Bounding Data Races in Space and Time

KC Sivaramakrishnan

University of Cambridge OCaml Labs Darwin College, Cambridge 1851 Royal Commission

  • 1
slide-2
SLIDE 2

Multicore OCaml

2

slide-3
SLIDE 3

Multicore OCaml

  • OCaml is an industrial-strength, functional programming

language

★ Projects: MirageOS unikernel, Coq proof assistant, F* programming language ★ Companies: Facebook (Hack, Flow, Infer, Reason), Microsoft (Everest, F*),

JaneStreet (all trading & support systems), Docker (Docker for Mac & Windows), Citrix (XenStore)

2

slide-4
SLIDE 4

Multicore OCaml

  • OCaml is an industrial-strength, functional programming

language

★ Projects: MirageOS unikernel, Coq proof assistant, F* programming language ★ Companies: Facebook (Hack, Flow, Infer, Reason), Microsoft (Everest, F*),

JaneStreet (all trading & support systems), Docker (Docker for Mac & Windows), Citrix (XenStore)

  • No multicore support!

2

slide-5
SLIDE 5

Multicore OCaml

  • OCaml is an industrial-strength, functional programming

language

★ Projects: MirageOS unikernel, Coq proof assistant, F* programming language ★ Companies: Facebook (Hack, Flow, Infer, Reason), Microsoft (Everest, F*),

JaneStreet (all trading & support systems), Docker (Docker for Mac & Windows), Citrix (XenStore)

  • No multicore support!
  • Multicore OCaml

★ Native support for concurrency and parallelism in OCaml ★ Lead from OCaml Labs + (JaneStreet, Microsoft Research, INRIA).

2

slide-6
SLIDE 6

Modelling Memory

3

slide-7
SLIDE 7

Modelling Memory

  • How do you reason about access to memory?

3

slide-8
SLIDE 8

Modelling Memory

  • How do you reason about access to memory?

★ Spoiler: No single global sequentially consistent memory 3

slide-9
SLIDE 9

Modelling Memory

  • How do you reason about access to memory?

★ Spoiler: No single global sequentially consistent memory

  • Modern multicore processors reorder instructions for

performance

3

slide-10
SLIDE 10

Modelling Memory

  • How do you reason about access to memory?

★ Spoiler: No single global sequentially consistent memory

  • Modern multicore processors reorder instructions for

performance

Thread 1 r1 = b Thread 2 r2 = a Initially a = 0 && b =0 r1 == 0 && r2 ==0 ??? a = 1 b = 1

3

slide-11
SLIDE 11

Modelling Memory

  • How do you reason about access to memory?

★ Spoiler: No single global sequentially consistent memory

  • Modern multicore processors reorder instructions for

performance

Thread 1 r1 = b Thread 2 r2 = a Initially a = 0 && b =0 r1 == 0 && r2 ==0 ??? Allowed under x86, ARM, POWER a = 1 b = 1

3

slide-12
SLIDE 12

Modelling Memory

  • How do you reason about access to memory?

★ Spoiler: No single global sequentially consistent memory

  • Modern multicore processors reorder instructions for

performance

Thread 1 r1 = b Thread 2 r2 = a Initially a = 0 && b =0 r1 == 0 && r2 ==0 ??? Allowed under x86, ARM, POWER a = 1 b = 1

Write buffering

3

slide-13
SLIDE 13

Modelling Memory

  • How do you reason about access to memory?

★ Spoiler: No single global sequentially consistent memory

  • Modern multicore processors reorder instructions for

performance

Thread 1 r1 = b Thread 2 r2 = a Initially a = 0 && b =0 r1 == 0 && r2 ==0 ??? Allowed under x86, ARM, POWER a = 1 b = 1

Write buffering

4

slide-14
SLIDE 14

Modelling Memory

  • Compilers optimisations also reorder memory access

instructions

5

slide-15
SLIDE 15

Modelling Memory

  • Compilers optimisations also reorder memory access

instructions

5

Thread 1 r1 = a * 2 r2 = b + 1 r3 = a * 2 Thread 1 r1 = a * 2 r2 = b + 1 r3 = r1

CSE

− − →

slide-16
SLIDE 16

Modelling Memory

  • Compilers optimisations also reorder memory access

instructions

5

Thread 1 r1 = a * 2 r2 = b + 1 r3 = a * 2 Thread 1 r1 = a * 2 r2 = b + 1 r3 = r1 Initially &a == &b && a = b = 1

CSE

− − →

slide-17
SLIDE 17

Modelling Memory

  • Compilers optimisations also reorder memory access

instructions

5

Thread 1 r1 = a * 2 r2 = b + 1 r3 = a * 2 Thread 1 r1 = a * 2 r2 = b + 1 r3 = r1 Initially &a == &b && a = b = 1 Thread 2 b = 0

CSE

− − →

slide-18
SLIDE 18

Modelling Memory

  • Compilers optimisations also reorder memory access

instructions

5

Thread 1 r1 = a * 2 r2 = b + 1 r3 = a * 2 Thread 1 r1 = a * 2 r2 = b + 1 r3 = r1 Initially &a == &b && a = b = 1 Thread 2 b = 0 r1 == 2 && r2 == 0 && r3 == 0

CSE

− − →

slide-19
SLIDE 19

Modelling Memory

  • Compilers optimisations also reorder memory access

instructions

5

Thread 1 r1 = a * 2 r2 = b + 1 r3 = a * 2 Thread 1 r1 = a * 2 r2 = b + 1 r3 = r1 Initially &a == &b && a = b = 1 Thread 2 b = 0 r1 == 2 && r2 == 0 && r3 == 0 r1 == 2 && r2 == 0 && r3 == 2

CSE

− − →

slide-20
SLIDE 20

Modelling Memory

  • Compilers optimisations also reorder memory access

instructions

6

Thread 1 r1 = a * 2 r2 = b + 1 r3 = a * 2 Thread 1 r1 = a * 2 r2 = b + 1 r3 = r1 Thread 2 b = 0 r1 == 2 && r2 == 0 && r3 == 0 r1 == 2 && r2 == 0 && r3 == 2 Initially &a == &b && a = b = 1

CSE

− − →

slide-21
SLIDE 21

Memory Model

  • Unambiguous specification of program outcomes

★ More than just thread interleavings

7

Memory model OCaml compiler

slide-22
SLIDE 22

Memory Model

  • Unambiguous specification of program outcomes

★ More than just thread interleavings

  • Memory Model Desiderata

★ Not too weak (good for programmers) ★ Not too strong (good for hardware) ★ Admits optimisations (good for compilers) ★ Mathematically rigorous (good for verification)

7

Memory model OCaml compiler

slide-23
SLIDE 23

Memory Model

  • Unambiguous specification of program outcomes

★ More than just thread interleavings

  • Memory Model Desiderata

★ Not too weak (good for programmers) ★ Not too strong (good for hardware) ★ Admits optimisations (good for compilers) ★ Mathematically rigorous (good for verification)

  • Difficult to get right

★ C/C++11 memory model is flawed ★ Java memory model is flawed ★ Several papers every year in top PL conferences

proposing / fixing models

7

Memory model OCaml compiler

slide-24
SLIDE 24

Memory Model: Programmer’s view

8

slide-25
SLIDE 25

Memory Model: Programmer’s view

  • Data race

★ Concurrent access to memory location, one of which is a write 8

slide-26
SLIDE 26

Memory Model: Programmer’s view

  • Data race

★ Concurrent access to memory location, one of which is a write

  • Sequential consistency (SC)

★ No intra-thread reordering, only inter-thread interleaving 8

slide-27
SLIDE 27

Memory Model: Programmer’s view

  • Data race

★ Concurrent access to memory location, one of which is a write

  • Sequential consistency (SC)

★ No intra-thread reordering, only inter-thread interleaving

  • DRF-SC: primary tool in concurrent programmers arsenal

★ If a program has no races (under SC semantics), then the program has SC

semantics

★ Well-synchronised programs do not have surprising behaviours

8

slide-28
SLIDE 28

Memory Model: Programmer’s view

  • Data race

★ Concurrent access to memory location, one of which is a write

  • Sequential consistency (SC)

★ No intra-thread reordering, only inter-thread interleaving

  • DRF-SC: primary tool in concurrent programmers arsenal

★ If a program has no races (under SC semantics), then the program has SC

semantics

★ Well-synchronised programs do not have surprising behaviours

  • Our observation: DRF-SC is too weak for programmers

8

slide-29
SLIDE 29

C/C++ Memory Model

  • C/C++ (C11) memory model offers DRF-SC, but..

9

slide-30
SLIDE 30

C/C++ Memory Model

  • C/C++ (C11) memory model offers DRF-SC, but..

★ If a program has races (even benign), then the behaviour is undefined!

9

slide-31
SLIDE 31

C/C++ Memory Model

  • C/C++ (C11) memory model offers DRF-SC, but..

★ If a program has races (even benign), then the behaviour is undefined! ★ Most C/C++ programs have races => most C/C++ programs are

allowed to crash and burn

9

slide-32
SLIDE 32

C/C++ Memory Model

  • C/C++ (C11) memory model offers DRF-SC, but..

★ If a program has races (even benign), then the behaviour is undefined! ★ Most C/C++ programs have races => most C/C++ programs are

allowed to crash and burn

  • Races on unrelated locations can affect behaviour

9

slide-33
SLIDE 33

C/C++ Memory Model

  • C/C++ (C11) memory model offers DRF-SC, but..

★ If a program has races (even benign), then the behaviour is undefined! ★ Most C/C++ programs have races => most C/C++ programs are

allowed to crash and burn

  • Races on unrelated locations can affect behaviour

★ We would like a memory model where data races are bounded in

space

9

slide-34
SLIDE 34
  • Java also offers DRF-SC

★ Unlike C++, type safety necessitates defined behaviour under races

10

Java Memory Model

slide-35
SLIDE 35
  • Java also offers DRF-SC

★ Unlike C++, type safety necessitates defined behaviour under races ★ No data races in space, but allows races in time…

10

Java Memory Model

slide-36
SLIDE 36
  • Java also offers DRF-SC

★ Unlike C++, type safety necessitates defined behaviour under races ★ No data races in space, but allows races in time…

10

Java Memory Model

int a; volatile bool flag;

slide-37
SLIDE 37
  • Java also offers DRF-SC

★ Unlike C++, type safety necessitates defined behaviour under races ★ No data races in space, but allows races in time…

10

Java Memory Model

int a; volatile bool flag; Thread 1 a = 1; flag = true;

slide-38
SLIDE 38
  • Java also offers DRF-SC

★ Unlike C++, type safety necessitates defined behaviour under races ★ No data races in space, but allows races in time…

10

Java Memory Model

int a; volatile bool flag; Thread 1 a = 1; flag = true; Thread 2 a = 2; if (flag) { // no race here r1 = a; r2 = a; }

slide-39
SLIDE 39
  • Java also offers DRF-SC

★ Unlike C++, type safety necessitates defined behaviour under races ★ No data races in space, but allows races in time…

10

Java Memory Model

int a; volatile bool flag; Thread 1 a = 1; flag = true; Thread 2 a = 2; if (flag) { // no race here r1 = a; r2 = a; } r1 == 1 && r2 == 2 is allowed

slide-40
SLIDE 40
  • Java also offers DRF-SC

★ Unlike C++, type safety necessitates defined behaviour under races ★ No data races in space, but allows races in time…

10

Java Memory Model

int a; volatile bool flag; Thread 1 a = 1; flag = true; Thread 2 a = 2; if (flag) { // no race here r1 = a; r2 = a; } r1 == 1 && r2 == 2 is allowed

Races in the past affects future

slide-41
SLIDE 41

Java Memory Model

  • Future data races can affect the past

11

slide-42
SLIDE 42

Java Memory Model

  • Future data races can affect the past

11

Class C { int x; }

slide-43
SLIDE 43

Thread 1 C c = new C(); c.x = 42; r1 = c.x;

Java Memory Model

  • Future data races can affect the past

11

Class C { int x; } Can assert (r1 == 42) fail?

slide-44
SLIDE 44

Java Memory Model

  • Future data races can affect the past

12

Class C { int x; } C g; Thread 1 C c = new C(); c.x = 42; r1 = c.x; g = c; Thread 2 g.x = 7; Can assert (r1 == 42) fail?

slide-45
SLIDE 45

Java Memory Model

  • Future data races can affect the past

13

Class C { int x; } C g; Thread 1 C c = new C(); c.x = 42; r1 = c.x; g = c; Thread 2 g.x = 7;

slide-46
SLIDE 46

Java Memory Model

  • Future data races can affect the past

13

Class C { int x; } C g; Thread 1 C c = new C(); c.x = 42; r1 = c.x; g = c; Thread 2 g.x = 7; assert (r1 == 42) fails

slide-47
SLIDE 47

Java Memory Model

  • Future data races can affect the past

13

Class C { int x; } C g; Thread 1 C c = new C(); c.x = 42; r1 = c.x; g = c; Thread 2 g.x = 7; assert (r1 == 42) fails

  • We would like a memory model that bounds data races in time
slide-48
SLIDE 48

OCaml Memory Model: Goal

14

slide-49
SLIDE 49
  • Language memory models should specify behaviours under data

races

OCaml Memory Model: Goal

14

slide-50
SLIDE 50
  • Language memory models should specify behaviours under data

races

★ Not because they are useful

OCaml Memory Model: Goal

14

slide-51
SLIDE 51
  • Language memory models should specify behaviours under data

races

★ Not because they are useful ★ But to limit their damage

OCaml Memory Model: Goal

14

slide-52
SLIDE 52
  • Language memory models should specify behaviours under data

races

★ Not because they are useful ★ But to limit their damage

OCaml Memory Model: Goal

14

If I read a variable twice and there are no concurrent writes, then both reads return the same value

slide-53
SLIDE 53

OCaml MM: Contributions

15

  • Memory Model Desiderata

★ Not too weak (good for

programmers)

★ Not too strong (good for

hardware)

★ Admits optimisations (good for

compilers)

★ Mathematically rigorous (good for

verification)

  • OCaml Memory model

★ Local version of DRF-SC — key

discovery

★ Free on x86, 0.6% overhead on

ARM, 2.6% overhead on POWER

★ Allows most common compiler

  • ptimisations

★ Simple operational and axiomatic

semantics + proved soundness (optimization + to-hardware)

slide-54
SLIDE 54

Local DRF

16

slide-55
SLIDE 55

Local DRF

  • If there are no data races,

16

slide-56
SLIDE 56

Local DRF

  • If there are no data races,

★ on some variables (space) 16

slide-57
SLIDE 57

Local DRF

  • If there are no data races,

★ on some variables (space) ★ in some interval (time) 16

slide-58
SLIDE 58

Local DRF

  • If there are no data races,

★ on some variables (space) ★ in some interval (time) ★ then the program has SC behaviour on those variables in that time interval 16

slide-59
SLIDE 59

Local DRF

  • If there are no data races,

★ on some variables (space) ★ in some interval (time) ★ then the program has SC behaviour on those variables in that time interval

  • Space = {all variables} && Time = whole execution => DRF-SC

16

slide-60
SLIDE 60

Local DRF

  • If there are no data races,

★ on some variables (space) ★ in some interval (time) ★ then the program has SC behaviour on those variables in that time interval

  • Space = {all variables} && Time = whole execution => DRF-SC

16

Thread 1 msg = 1; b = 0; Flag = 1; Thread 2 b = 1; if (Flag) { r = msg; } Flag is atomic

slide-61
SLIDE 61

Local DRF

  • If there are no data races,

★ on some variables (space) ★ in some interval (time) ★ then the program has SC behaviour on those variables in that time interval

  • Space = {all variables} && Time = whole execution => DRF-SC

16

Thread 1 msg = 1; b = 0; Flag = 1; Thread 2 b = 1; if (Flag) { r = msg; } Flag is atomic

slide-62
SLIDE 62

Local DRF

  • If there are no data races,

★ on some variables (space) ★ in some interval (time) ★ then the program has SC behaviour on those variables in that time interval

  • Space = {all variables} && Time = whole execution => DRF-SC

16

Thread 1 msg = 1; b = 0; Flag = 1; Thread 2 b = 1; if (Flag) { r = msg; } Flag is atomic Due to local DRF, despite the race on b, message-passing idiom still works!

slide-63
SLIDE 63

Formal Memory Model

17

slide-64
SLIDE 64

Formal Memory Model

17

  • Most programmers can live with local DRF

★ Experts demand more (concurrency libraries, high-performance code, etc.)

slide-65
SLIDE 65

Formal Memory Model

17

  • Most programmers can live with local DRF

★ Experts demand more (concurrency libraries, high-performance code, etc.)

  • Simple operational semantics that captures all of the allowed

behaviours

slide-66
SLIDE 66

Formal Memory Model

17

  • Most programmers can live with local DRF

★ Experts demand more (concurrency libraries, high-performance code, etc.)

  • Simple operational semantics that captures all of the allowed

behaviours

slide-67
SLIDE 67

Visualising operational semantics

18

Non atomic a b c 1 2 3 4 5 6 7 Histories

time

− − →

5

slide-68
SLIDE 68

Visualising operational semantics

18

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories

time

− − →

5

slide-69
SLIDE 69

Visualising operational semantics

18

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(b)

time

− − →

5

slide-70
SLIDE 70

Visualising operational semantics

18

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(b) -> 3/4/5

time

− − →

5

slide-71
SLIDE 71

Visualising operational semantics

18

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(b) -> 3/4/5 write(c,10)

time

− − →

5

slide-72
SLIDE 72

Visualising operational semantics

19

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(b) -> 3/4/5 write(c,10) 10

time

− − →

5

slide-73
SLIDE 73

Visualising operational semantics

19

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(b) -> 3/4/5 write(c,10) 10

time

− − →

Atomic

A B

10 5 5

slide-74
SLIDE 74

Visualising operational semantics

19

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(b) -> 3/4/5 write(c,10) 10

time

− − →

Atomic

A B

10 5 5

slide-75
SLIDE 75

Visualising operational semantics

20

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(B) 10

time

− − →

Atomic

A B

10 5 5

slide-76
SLIDE 76

Visualising operational semantics

20

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(B) 10

time

− − →

Atomic

A B

10 5

  • > 5

5

slide-77
SLIDE 77

Visualising operational semantics

21

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(B) 10

time

− − →

Atomic

A B

10 5

  • > 5

5

slide-78
SLIDE 78

Visualising operational semantics

21

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(B) 10

time

− − →

Atomic

A B

10 5

  • > 5

write (A,20) 5

slide-79
SLIDE 79

Visualising operational semantics

22

Non atomic a b c 1 2 3 4 5 6 7

Thread 1 Thread 2

Histories read(B) 10

time

− − →

Atomic

A B

20 5

  • > 5

write (A,20) 5

slide-80
SLIDE 80

Formalizing Local DRF

23

Trace

slide-81
SLIDE 81

Formalizing Local DRF

23

Trace

Machine state = State of all threads + Heap

slide-82
SLIDE 82

Formalizing Local DRF

23

Trace

Machine state = State of all threads + Heap Memory access

slide-83
SLIDE 83

Formalizing Local DRF

23

Trace

Machine state = State of all threads + Heap Memory access

  • Pick a set of L of locations
slide-84
SLIDE 84

Formalizing Local DRF

23

Trace

Machine state = State of all threads + Heap Memory access

  • Pick a set of L of locations

Space

slide-85
SLIDE 85

Formalizing Local DRF

23

Trace

Machine state = State of all threads + Heap Memory access

  • Pick a set of L of locations
  • Pick a machine state M where there are no ongoing races in L

★ M is said to be L-stable

Space

slide-86
SLIDE 86

Formalizing Local DRF

23

Trace

Machine state = State of all threads + Heap Memory access

  • Pick a set of L of locations
  • Pick a machine state M where there are no ongoing races in L

★ M is said to be L-stable

  • Local DRF Theorem

★ Starting from an L-stable state M, until the next race on any location in L

under SC semantics, the program has SC semantics

Space

slide-87
SLIDE 87

Formalizing Local DRF

23

Trace

Machine state = State of all threads + Heap Memory access

  • Pick a set of L of locations
  • Pick a machine state M where there are no ongoing races in L

★ M is said to be L-stable

  • Local DRF Theorem

★ Starting from an L-stable state M, until the next race on any location in L

under SC semantics, the program has SC semantics

Space Time

slide-88
SLIDE 88
  • Local DRF prohibits certain hardware and software
  • ptimisations

★ Preserve load-to-store ordering

Performance Implication

24

slide-89
SLIDE 89
  • Local DRF prohibits certain hardware and software
  • ptimisations

★ Preserve load-to-store ordering

  • No compiler optimisation that reorders load-to-store ordering

is allowed

Performance Implication

24

slide-90
SLIDE 90
  • Local DRF prohibits certain hardware and software
  • ptimisations

★ Preserve load-to-store ordering

  • No compiler optimisation that reorders load-to-store ordering

is allowed

Performance Implication

24

r1 = a; b = c; a = r1;

Redundant store elimination

− − − − − − − − − − − − − − − →

r1 = a; b = c; ;

slide-91
SLIDE 91
  • Local DRF prohibits certain hardware and software
  • ptimisations

★ Preserve load-to-store ordering

  • No compiler optimisation that reorders load-to-store ordering

is allowed

Performance Implication

24

r1 = a; b = c; a = r1;

Redundant store elimination

− − − − − − − − − − − − − − − →

r1 = a; b = c; ;

slide-92
SLIDE 92
  • Local DRF prohibits certain hardware and software
  • ptimisations

★ Preserve load-to-store ordering

  • No compiler optimisation that reorders load-to-store ordering

is allowed

Performance Implication

24

r1 = a; b = c; a = r1;

Redundant store elimination

− − − − − − − − − − − − − − − →

r1 = a; b = c; ;

slide-93
SLIDE 93
  • Local DRF prohibits certain hardware and software
  • ptimisations

★ Preserve load-to-store ordering

  • No compiler optimisation that reorders load-to-store ordering

is allowed

Performance Implication

24

r1 = a; b = c; a = r1;

Redundant store elimination

− − − − − − − − − − − − − − − →

r1 = a; b = c; ;

slide-94
SLIDE 94
  • Local DRF prohibits certain hardware and software
  • ptimisations

★ Preserve load-to-store ordering

  • No compiler optimisation that reorders load-to-store ordering

is allowed

  • ARM & POWER do not preserve load-to-store ordering

★ Insert necessary synchronisation between every mutable load and store ★ What is the performance cost?

Performance Implication

24

r1 = a; b = c; a = r1;

Redundant store elimination

− − − − − − − − − − − − − − − →

r1 = a; b = c; ;

slide-95
SLIDE 95

Performance

25

slide-96
SLIDE 96

Performance

25

0.6% overhead on AArch64 (ARMv8)

slide-97
SLIDE 97

Performance

25

0.6% overhead on AArch64 (ARMv8) Free on x86, 2.6% on POWER

slide-98
SLIDE 98

Summary

  • OCaml memory model

★ Balances comprehensibility (Local DRF theorem) and Performance (free on

x86, 0.6% on ARMv8, 2.6% on POWER)

★ Allows common compiler optimisations ★ Compilation + Optimisations proved sound 26

slide-99
SLIDE 99

Summary

  • OCaml memory model

★ Balances comprehensibility (Local DRF theorem) and Performance (free on

x86, 0.6% on ARMv8, 2.6% on POWER)

★ Allows common compiler optimisations ★ Compilation + Optimisations proved sound

  • Proposed as the memory model for OCaml

★ Also suitable for other safe languages (Swift, WebAssembly, JavaScript) 26