counting immutable beans - appendix · 2020. 6. 1. · counting immutable beans - appendix 3 a.3...

13
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Counting Immutable Beans - Appendix Reference Counting Optimized for Purely Functional Programming SEBASTIAN ULLRICH, Karlsruhe Institute of Technology, Germany LEONARDO DE MOURA, Microsoft Research, USA Most functional languages rely on some kind of garbage collection for automatic memory management. They usually eschew reference counting in favor of a tracing garbage collector, which has less bookkeeping overhead at runtime. On the other hand, having an exact reference count of each value can enable optimizations such as destructive updates. We explore these optimization opportunities in the context of an eager, purely functional programming language. We propose a new mechanism for efficiently reclaiming memory used by nonshared values, reducing stress on the global memory allocator. We describe an approach for minimizing the number of reference counts updates using borrowed references and a heuristic for automatically inferring borrow annotations. We implemented all these techniques in a new compiler for an eager and purely functional programming language with support for multi-threading. Our preliminary experimental results demonstrate our approach is competitive and often outperforms state-of-the-art compilers. Additional Key Words and Phrases: purely functional programming, reference counting, Lean A APPENDIX A.1 Pure semantics For the sake of completeness, we give a semantics specification on λ pure in addition to the λ RC semantics given in the paper. ρ Ctxt = Var Value v Value ::= ctor i v | pap c v Const-App-Full δ ( c ) = λ y c . F v = ρ ( y) [ y c 7v ]⊢ F v ρ c y v Const-App-Part δ ( c ) = λ y c . F v = ρ ( y) | v | <| y c | ρ pap c y pap c v Var-App-Full ρ (x ) = pap c v δ ( c ) = λ y c . F v = ρ ( y) [ y c 7vv ]⊢ F v ′′ ρ xy v ′′ Authors’ addresses: Sebastian Ullrich, Karlsruhe Institute of Technology, Germany, [email protected]; Leonardo de Moura, Microsoft Research, USA, [email protected]. 2020. XXXX-XXXX/2020/9-ART $15.00 https://doi.org/ , Vol. 1, No. 1, Article . Publication date: September 2020.

Upload: others

Post on 04-Oct-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

Counting Immutable Beans - AppendixReference Counting Optimized for Purely Functional Programming

SEBASTIAN ULLRICH, Karlsruhe Institute of Technology, Germany

LEONARDO DE MOURA,Microsoft Research, USA

Most functional languages rely on some kind of garbage collection for automatic memory management. They

usually eschew reference counting in favor of a tracing garbage collector, which has less bookkeeping overhead

at runtime. On the other hand, having an exact reference count of each value can enable optimizations such as

destructive updates. We explore these optimization opportunities in the context of an eager, purely functional

programming language. We propose a new mechanism for efficiently reclaiming memory used by nonshared

values, reducing stress on the global memory allocator. We describe an approach for minimizing the number

of reference counts updates using borrowed references and a heuristic for automatically inferring borrow

annotations. We implemented all these techniques in a new compiler for an eager and purely functional

programming language with support for multi-threading. Our preliminary experimental results demonstrate

our approach is competitive and often outperforms state-of-the-art compilers.

Additional Key Words and Phrases: purely functional programming, reference counting, Lean

A APPENDIXA.1 Pure semanticsFor the sake of completeness, we give a semantics specification on λpure in addition to the λRCsemantics given in the paper.

ρ ∈ Ctxt = Var ⇀ Value

v ∈ Value ::= ctori v | pap c v

Const-App-Full

δ (c) = λ yc. F v = ρ(y) [yc 7→ v] ⊢ F ⇓ v ′

ρ ⊢ c y ⇓ v ′

Const-App-Part

δ (c) = λ yc. F v = ρ(y) | v |< | yc |

ρ ⊢ pap c y ⇓ pap c v

Var-App-Full

ρ(x) = pap c v δ (c) = λ yc. F v ′ = ρ(y) [yc 7→ v v ′] ⊢ F ⇓ v ′′

ρ ⊢ x y ⇓ v ′′

Authors’ addresses: Sebastian Ullrich, Karlsruhe Institute of Technology, Germany, [email protected]; Leonardo de

Moura, Microsoft Research, USA, [email protected].

2020. XXXX-XXXX/2020/9-ART $15.00

https://doi.org/

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 2: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

2 Sebastian Ullrich and Leonardo de Moura

Var-App-Part

ρ(x) = pap c v δ (c) = λ yc. F v ′ = ρ(y) | v v ′ |< | yc |

ρ ⊢ x y ⇓ pap c v v ′

Ctor-App

v = ρ(y)

ρ ⊢ ctori y ⇓ ctori v

Proj

ρ(x) = ctorj v v ′ = vi

ρ ⊢ proji x ⇓ v ′

Return

ρ(x) = v

ρ ⊢ ret x ⇓ v

Let

ρ ⊢ e ⇓ v ρ[x 7→ v] ⊢ F ⇓ v ′

ρ ⊢ let x = e; F ⇓ v ′

Case

ρ(x) = ctori v ρ ⊢ Fi ⇓ v ′

ρ ⊢ case x of F ⇓ v ′

We furthermore extend the pure semantics to λRC in order to express semantic refinement forour compiler passes that only change the RC semantics of a program.

Inc

ρ ⊢ F ⇓ v

ρ ⊢ inc x ; F ⇓ v

Dec

ρ ⊢ F ⇓ v

ρ ⊢ dec x ; F ⇓ v

Reset

ρ ⊢ reset x ⇓ v

Reuse

ρ ⊢ ctori y ⇓ v

ρ ⊢ reuse x in ctori y ⇓ v

Definition 1. We say δB refines δA in the pure semantics if for each constant c with δA(c) = λ y. F ,we have δB (c) = λ y ′. F ′ and

[y 7→ v] ⊢ F ⇓ v ⇐⇒ [y ′ 7→ v] ⊢ F ′ ⇓ v

Note that there are no assertions about constants in δB but not in δA.

A.2 Well-formednessDefinition 2 (well-formedness of pure programs). Used variables should be defined, and

defined variables should be used. Applications should be of the correct arity. Bindings should be fresh.

∀c ∈ dom(δ ). δ ⊢pure c

⊢pure δ

δ (c) = λ y. F y ⊢pure F

δ ⊢pure c

Γ, x ⊢pure ret x

Γ, x ⊢pure F

Γ, x ⊢pure case x of F

Γ ⊢pure e z ∈ FV (F ) z < Γ Γ, z ⊢pure F

Γ ⊢pure let z = e; F

δ (c) = λ yc . F′ | y |=| yc |

Γ,y ⊢pure c y Γ,y ⊢pure pap c y Γ, x,y ⊢pure x y

Γ,y ⊢pure cnstri y Γ, x ⊢pure proji x

We will assume ⊢pure δ .

Theorem 1. If Γ ⊢pure F , then FV(F ) ⊆ Γ.

Proof. By induction over F . □

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 3: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

Counting Immutable Beans - Appendix 3

A.3 reset/reuseDefinition 3 (Well-formedness of reset/reuse instructions). Reset variables form a sepa-

rate, affine context ∆. They are introduced by reset and may be consumed by reuse. dec instructionsintroduced later will turn the context linear, as postulated by the full type system below.

∀c ∈ dom(δ ). δ ⊢reuse c

⊢reuse δ

δ (c) = λ y. F y; · ⊢reuse F

δ ⊢reuse c

Γ, x ;∆ ⊢reuse ret x

Γ, x ;∆ ⊢reuse F

Γ, x ;∆ ⊢reuse case x of F

Γ ⊢pure e z ∈ FV (F ) z < Γ ∆ Γ, z;∆ ⊢reuse F

Γ;∆ ⊢reuse let z = e; F

z < Γ ∆ Γ;∆, z ⊢reuse F

Γ;∆ ⊢reuse let z = reset e; F

Γ;∆ ⊢reuse F

Γ;∆, x ⊢reuse let z = reuse x in ctori y; F

Theorem 2. For the specific δreuse described in the paper, we have ⊢reuse δreuse. Moreover, δreuserefines δ in the pure semantics.

Theorem 3. If Γ;∆ ⊢reuse F , then FV(F ) ⊆ Γ ∆.

Proof. By induction over F . □

A.4 Borrow inferenceDefinition 4 (Program after borrow inference). We assume that for every constant c ∈ δreuse

there exists an unusued constant name cO.

δβ = δ ′reuse[cO 7→ λ y. c y | B ∈ β(c), δreuse(c) = λ y. F ]

where δ ′reuse is obtained from δreuse by replacing every occurrence of pap c y where B ∈ β(c) by pap cO y.

Definition 5 (Well-formedness of borrow inference). β is arity-correct. Partially appliedconstants do not have borrowed parameters.

⊢reuse δ δ ⊢β c ∀c ∈ dom(δ )

⊢β δ

δ (c) = λ y. F | y |=| β(c) | ⊢β F

δ ⊢β c

B < β(c) ⊢β F

⊢β let x = pap c y; F ⊢β ret x

The rules for all other instructions proceed by direct induction on F or F .

Theorem 4. For δβ from Definition 4 and any arity-correct β , we have ⊢β δβ . Moreover, δβ refinesδreuse in the pure semantics.

A.5 A type system for RC-correct programsA program’s behavior should not be changed by compiling it to (or optimizing it in) λRC. Beforedesigning the compiler, it is helpful to capture the global, dynamic invariants necessary for this in

a static type system that reasons about just the local context of a function.

Intuitively, a program is RC-correct if

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 4: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

4 Sebastian Ullrich and Leonardo de Moura

(1) owned variables are locally count-correct: every owned variable is ultimately consumed

or deced on each control flow path, with every inc allowing and necessitating one more

consumption,

(2) values are not freed while borrowed, and

(3) values from reset are handled by exactly one reuse or dec on each control flow path, and

are not used in any other context.

The second constraint deserves further elaboration: we will assume that variables are only

borrowed when passed to borrowed parameters, in which case we assume that the borrowed

variable is valid for the entire function call, and no

The type system formalizing these constraints is quite simple: since types have been erased from

λpure, the only types are O, B, and R for owned, borrowed, and reset references, respectively.

τ ∈ Ty ::= O | B | R

The type system is linear to represent conditions (1) and (3); for borrowed references, we add the

usual weakening and contraction rules from intuitionistic linear logic [Benton et al. 1993] to model

their non-linear, or intuitionistic, semantics.

Ty-Var

x : τ ⊢RC x : τ

Ty-Weaken

Γ ⊢RC e : τ

Γ, x : B ⊢RC e : τ

Ty-Contract

Γ, x : B, x : B ⊢RC e : τ

Γ, x : B ⊢RC e : τ

Ty-Contract-F

Γ, x : B, x : B ⊢RC F

Γ, x : B ⊢RC F

We define well-typed programs and constants in terms of well-typed function bodies; the return

type is elided since it is always O.

⊢β δ ∀c ∈ dom(δ ). δ ⊢RC c

⊢RC δ

δ (c) = λ y. F y : β(c) ⊢RC F

δ ⊢RC c

inc introduces a new owned reference from a borrowed or owned reference, dec consumes an

owned or reset reference.

Ty-Inc

τ ∈ {O,B} Γ, x : τ , x : O ⊢RC F

Γ, x : τ ⊢RC inc x ; F

Ty-Dec

τ ∈ {O,R} Γ ⊢RC F

Γ, x : τ ⊢RC dec x ; F

Note that the first rule can introduce the same variable with two different types. It may help

to view our type system as a capability system: A hypothesis of type O or R grants (exactly) one

consuming usage, while one of type B grants only non-consuming usage.

Return values must be owned, while non-consuming, immediate uses like in case can be owned

or borrowed.

Ty-Return

Γ ⊢RC x : O

Γ ⊢RC ret x

Ty-Case

τ ∈ {O,B} Γ, x : τ ⊢RC F

Γ, x : τ ⊢RC case x of F

Applications are typed by splitting up the linear context. Arguments to partial, variable and

constructor applications must be owned because, in general, we cannot statically assert that the

resulting value will not escape the current function and thus the scope of borrowed references.

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 5: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

Counting Immutable Beans - Appendix 5

Ty-Const-App-Full

Γ ⊢RC y : β(c)

Γ ⊢RC c y : O

Ty-Const-App-Part

β(c) = O

y : O ⊢RC pap c y : O

Ty-Var-App

x : O,y : O ⊢RC x y : O

Ty-Cnstr-App

y : O ⊢RC cnstri y : O

Ty-Reset

x : O ⊢RC reset x : R

Ty-Reuse

x : R,y : O ⊢RC reuse x in cnstri y : O

In order to type (saturated) applications with borrowed parameters, the rule for let should

support temporarily obtaining a borrowed reference from an owned reference, much like Wadler

[1990]’s let! construct. The rule makes the owned reference unavailable during the call to ensure

that the borrowed reference is valid for that duration. The result type of e ensures that the borrowcannot survive past the call.

Ty-Let

Γ, x : B ⊢RC e : τ τ ∈ {O,R} ∆, x : O, z : τ ⊢RC F

Γ,∆, x : O ⊢RC let z = e; F

Projections are handled specially. It is sound to treat the projection of a borrowed reference as

borrowed because borrowed references are assumed to be valid for the entire function call. On the

other hand, when projecting an owned reference, we conservatively treat the result as owned as

well by requiring that it is incremented immediately; a more flexible model would need a more

sophisticated “borrow checker” that makes sure that the projection cannot outlive the projected

reference.

Ty-Proj-Bor

Γ, x : B,y : B ⊢RC F

Γ, x : B ⊢RC let y = proji x ; F

Ty-Proj-Own

Γ, x : O,y : O ⊢RC F

Γ, x : O ⊢RC let y = proji x ; inc y; F

Definition 6. The function valof : Loc × State ⇀ Valuepure is defined as follows:

valof(l,σ ) = ctori valof(l ′,σ ) if σ (l) = ctori l ′

valof(l,σ ) = pap c valof(l ′,σ ) if σ (l) = pap c l ′

Theorem 5 (semantics preservation). Suppose the program is well-typed, ⊢RC δ , and c is aparameter-less constant, δ (c) = F .(1) If ⊢ F ⇓ v , then ⊢ ⟨F , ∅⟩ ⇓ ⟨l,σ ⟩ and valof(l,σ ) = v .(2) If ⊢ ⟨F , ∅⟩ ⇓ ⟨l,σ ⟩, then ⊢ F ⇓ valof(l,σ ).

Proof. Below. The proof directly follows Chirimar et al. [1996]’s proof of this theorem for a

similar linear type system (we direct interested readers to this paper for proofs of further properties

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 6: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

6 Sebastian Ullrich and Leonardo de Moura

such as freedom of memory leaks). The fundamental idea of inducing a memory graph from the

heap and local variables and proving that the in-degrees of its nodes is equal to the values’ reference

counts is directly applicable to our owned references. We will quickly discuss parts of our system

not present in theirs that needed to be fitted into the proofs:

• Borrowed references do not change the reference count and thus the definition of the memory

graph does not need to be adjusted. However, the proof needed to be extended with an

additional hypothesis that every borrowed reference is reachable from an owned root variablein a parent stack frame, which implies that the borrowed reference is valid for the duration

of the current function call.

• Reset references are restricted by the semantics and type system to be used only in reuseand dec, but otherwise behave linearly like owned references. Because we replace their

former contents with⊥ instead of leaving them as dangling pointers, treating reset references

like owned references in the memory graph results in the correct behavior without further

changes. An additional assumption makes sure that every reset references does in fact have

this shape.

A.6 Proof of semantics preservationA memory graph G is a tuple (V , E, s, t, l) where (V , E, s, t) is a directed multigraph with a root(multi)set l ⊆ V 1

. The reference count of a vertex v ∈ V is the sum of inner and outer references

in-degree(v)+ | {i | v = li } |

A state is a pair (l,σ ) of a root set l into a store σ .

Definition 7. If S = (l,σ ) is a state, the memory graph G(S) induced by S is a memory graphwith dom(σ ) as its vertices and an edge from l ∈ dom(σ ) to every l ′ ∈ σ (l).

Definition 8. A state S = (l,σ ) is count-correct if, for each σ (l) = (v, i), the reference count of lin G(S) is i .

Definition 9. A state S = (l,σ ) is called regular, written R(S), provided the following conditionshold:R1 S is count-correct.R2 dom(σ ) is finite.R3 The reference count is non-zero for every l ∈ dom(σ ).

Definition 10 (Reference reachability). A reference l ′ is reachable from l in the store σ ,reachableσ (l, l

′), if there is a path from l to l ′ in G([],σ )2.

Theorem 6 (Memory Graph Laws).

B R(l,σ ) iff R(l ,σ ).D If R(l l ′,σ ), then R(l, dec(l ′,σ )).I If R(l,σ ), and l ′ ∈ dom(ρ), then R(l l ′, inc(l ′,σ )).

Proof.

B As is not a reference, it does not influence reference counts.

D By induction over the total sum of reference counts (which is finite by regularity).

1We will operate on such lists up to permutations without further mention

2The root set is irrelevant for this definition

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 7: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

Counting Immutable Beans - Appendix 7

I Trivial.

Theorem 7 (Preservation of regularity). Suppose

⊢RC δ , yO : O,yB : B,yR : R ⊢RC F , (program and body are well-formed)

dom(ρ) = yO yB yR,R(l ρ(yO yR),σ ), and (owned variables are rooted)

∀y ∈ yB. ∃l ∈ l . reachableσ (l, ρ(y)). (borrowed variables are reachable)

If ρ ⊢ ⟨F ,σ ⟩ ⇓ ⟨l ′,σ ′⟩, then R(l l ′,σ ′). Moreover, if l = l1 l2 and l ∈ dom(σ ) is not reachable froml1 ran(ρ) in G(l ran(ρ),σ ), then σ ′(l) = σ (l) and l is not reachable from l1 l

′ in G(l l ′,σ ′) (thereachability property).

Here l are roots outside of the current context, i.e. from a parent stack frame. Note that in our

model, borrowed references are assumed to be alive for the whole function call, i.e. they must be

reachable from a parent stack frame.

Proof. By induction over ρ ⊢ ⟨F ,σ ⟩ ⇓ ⟨l ′,σ ′⟩.

Case Let + Ctor-App

By case inversions of the typing assumption, we have Γ = y : O. Thus there exists y ′Osuch

that y y ′O= yO. For the IH we need to show R(l ρ(y ′

OyR) l

′,σ [l ′ 7→ (ctori ρ(y), 1)]) and the

reachability property. l ′ is fresh, so its in-degree is indeed 0. All ρ(y) have been moved from

roots into l ′, so they are count-correct as well. The reachability property holds because the

store is only extended, not modified, and all locations reachable from l ′ have already been

reachable from ρ(yO).Case Let + Const-App-Part/Var-App-Part

Analogously.

Case Let + Const-App-Full

We have F = let y = c y ′; F ′

, δ (c) = λ yc . Fc . We first apply the IH to Fc : by the typing

assumption, it is well-typed and the types of arguments correspond to their respective

parameter types, so owned arguments are rooted and borrowed variables are reachable

(either from l by the reachability assumption, or from someyO not passed to c but temporarily

borrowed in Ty-Let). We obtain that the new state is regular and fulfills the reachability

property after removing all owned variables passed to c from and adding l ′ to the root set.

Thus we can apply the IH to F ′.

To show the reachability property, assume l ∈ dom(σ ) is not reachable from l1 ran(ρ) where

l = l1 l2. Then by the first IH, it is unreachable from l1 l′in the new state and σ ′(l) = σ (l).

Thus we can conclude by the second IH. Like Chirimar et al. [1996], we will omit further

similar proofs of the reachability property.

Case Let + Var-App-Full

Similarly, but we need additional steps to argue for the regularity of the state passed to Fc :ρ(x) is a root by the inductive assumptions, but is not passed to either of Fc or F

′. dec thus

correctly removes it from the root set by law D. Conversely, the l ′ in σ (ρ(x)) are passed as

owned arguments not taken from existing roots (but reachable from the root ρ(x), i.e. indom(σ )), so inc correctly adds them to the root set by I.

Case Let + Proj

We have F = let y = proji x ; F′. We continue by case analysis of the typing assumption.

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 8: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

8 Sebastian Ullrich and Leonardo de Moura

Case Ty-Proj-BorWe have x,y : B, so x ∈ yB. Thus x is reachable by assumption, and so is y by the ctorreachability rule and transitivity. Therefore we can apply the IH.

Case Ty-Proj-Own

We have F ′ = inc y; F ′′and x,y : O, so x ∈ yO. Because y is both registered as a new root

and incremented, we can apply the IH to F ′′.

Case ReturnBy the typing assumption, x is the only owned variable left. Thus we can directly apply the

regularity assumption.

Case CaseNo changes to the context or store, so the IH applies immediately.

Case IncBy the typing assumption, we have τ ∈ {O,B}. In either case, ρ(x) is equal to or reachable

from a root and thus ρ(x) ∈ dom(σ ), so we are done by law I and the IH.

Case Decx is a root by the typing assumption, so we are done by law D and the IH.

Case Let + Reset-Uniq

It is easy to see that the new store is count-correct. While x changes its type, it remains a

root, so the state is regular and we can apply the IH.

Case Let + Reset-Shared

By laws B and D and the IH.

Case Let + Reuse-Uniq

Similarly to Ctor-App.

Case Let + Reuse-Shared

By the IH.

Lemma 1. Suppose

⊢RC δ , yO : O yB : B yR : R ⊢RC F , (program and body are well-formed)

dom(ρ) = yO yB yR,R(l ρ(yO yR),σ ), (owned variables are rooted)

∀y ∈ yB. ∃l ∈ l . reachableσ (l, ρ(y)), and (borrowed variables are reachable)

∀y ∈ yR. ρ(y) = ∨ ∃i,n, r .σ (ρ(y)) = (ctorin, r ). (reset variables are reset)

(1) If valof(ρ(yO yB),σ ) ⊢ F ⇓ v , then ρ ⊢ ⟨F ,σ ⟩ ⇓ ⟨l,σ ′⟩ and v = valof(l,σ ′).(2) If If ρ ⊢ ⟨F ,σ ⟩ ⇓ ⟨l,σ ′⟩, then valof(ρ(yO yB),σ ) ⊢ F ⇓ valof(l,σ ′).

Proof. The first part is proved by induction over valof(ρ(yO yB),σ ) ⊢ F ⇓ v .Case F = ret x

By valof(ρ,σ )(x) = valof(ρ(x),σ ).

Case F = case x of F ′

Directly by the IH.

Case F = inc x ; F ′

We have valof(ρ(yO yB x), inc(ρ(x),σ )) = valof(ρ(yO yB x),σ ) by the definition of valof , so

we can apply the IH.

Case F = dec x ; F ′

Let Γ, x : τ be the context. By R1, we have that all values reachable from Γ still have reference

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 9: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

Counting Immutable Beans - Appendix 9

count ≥ 1 in σ ′:= dec(ρ(x),σ ), so valof(Γ,σ ′) = valof(Γ,σ ) by the definition of dec, and we

can apply the IH.

Case F = let y = proji x ; F′ if x ∈ yO

By the typing assumption, we have F ′ = inc y; F ′′. Note that F ′

and F ′′are equivalent in

the pure semantics, so we can apply the IH to F ′′as well, after noticing that inc(·, ·) does not

affect valof(·, ·).Case F = let y = proji x ; F

′ if x ∈ yBBy the IH.

Case F = let y = reset x ; F ′

By either Reuse-Uniq or Reuse-Shared. In either case, the assumption about reset variables

is fulfilled and we can apply the IH. Note that the pure context is unchanged.

Case F = let y = reuse x in ctori y; F ′

By the assumption about reset references and the IH.

Case F = let z = c y; F ′

We have δ (c) = λ yc . Fc . In order to apply the IH on F ′, we need to show that the value

of all remaining context variables has not been changed by the call, which follows from

Theorem 7’s reachability property.

Case F = let z = pap c y; F ′

There exists an l ′ < dom(σ ) by R2. Apply the IH.

Case F = let z = ctori y; F ′

Analogously.

Case F = let z = x y; F ′

We have eraseRC(F ) = let z = x y; eraseRC(F′). By case distinction, the two possible cases

are Var-App-Full and Var-App-Part, which are handled similarly to the above cases.

The reverse direction is proved by induction over ρ ⊢ ⟨F ,σ ⟩ ⇓ ⟨l,σ ′⟩ with similar but simpler

cases. □

Theorem 8 (semantics preservation). Suppose the program is well-typed, ⊢RC δ , and c is aparameter-less constant, δ (c) = F .

(1) If ⊢ F ⇓ v , then ⊢ ⟨F , ∅⟩ ⇓ ⟨l,σ ⟩ and valof(l,σ ) = v .(2) If ⊢ ⟨F , ∅⟩ ⇓ ⟨l,σ ⟩, then ⊢ F ⇓ valof(l,σ ).

Proof. A direct corollary of Lemma 1. □

A.7 Proof of compilation well-typednessTheorem 9. For the specific δRC given in the paper, we have ⊢RC δRC.

Proof. We start with a helper lemma about C .

Lemma 2. C does not introduce new variables, FV(C(F )) = FV(F ).

Proof. By induction over F . □

By the definition of δRC, we need to show for each λ y. F ∈ δβ

y : β(c) ⊢RC O−(y,C(F )) with βl := [y 7→ β(c), ... 7→ O]

Aside: In this proof, we will style βl as an implicit variable to reduce verbosity.By the wellformedness of δβ (Theorem 4), we have ⊢β F and y; · ⊢reuse F .

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 10: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

10 Sebastian Ullrich and Leonardo de Moura

Note that all yi : O are alive in F ′:= O−(y,C(F )): If they do not occur in C(F ), they will occur in

a dec instruction from O−instead. Thus we can generalize the goal to

yO yR ⊆ FV (F ′) yO yB;yR ⊢reuse F ⊢β F yO yB yRdistinct

yO : O,yB : B,yR : R ⊢RC F ′with βl := [yB 7→ B, . . . 7→ O]

where yR := [] and yO yB := y.Unfolding O−

and applying the dec typing rule repeatedly, we remove all yO < FV(C(F )) and,reusing the name yO for the reduced variable list and applying Lemma 2, are left with

yO yR ⊆ FV (F ) yO yB;yR ⊢reuse F ⊢β F yO yB yRdistinct

yO : O,yB : B,yR : R ⊢RC C(F ) with βl := [yB 7→ B, . . . 7→ O]

We proceed by induction over F , but not before noting a peculiarity about this induction hypoth-

esis: Not only does the type context contain only owned variables that are alive in the remaining

body (as one may expect), it also contains each of them no more than once. It turns out that

duplicating a reference is only necessary just before applications, which will happen in between

the induction steps of the proof. In this sense, we see that the compiler keeps all reference counts

as low as possible.

Case F = ret xWe need to show

yO : O,yB : B,yR : R ⊢RC O+x (ret x)

By the first two inductive assumptions, we have yO yR ⊆ {x} and x ∈ yO yB, respectively.Together with the fourth assumption, x may appear at most once in either yO or yB.If βl (x) = B, it remains to be shown that

x : B,y : B ⊢RC inc x ; ret x

Applying the inc rule, we get to the same goal as in the case βl (x) = O:

x : O,y ′: B ⊢RC ret x

which is closed by the ret rule plus weakening.Case F = case x of F ′

We need to show

yO : O,yB : B,yR : R ⊢RC case x of O−(y ′,C(F ′))

where {y ′} = FV(case x of F ′). By the first two inductive assumptions, we have

yO yR ⊆ y ′

x ∈ yO yB, yO yB;yR ⊢reuse F ′

Using x ∈ yO yB, we can apply the case typing rule, leaving us with, for each F ′i ,

yO : O,yB : B,yR : R ⊢RC O−(y ′,C(F ′

i ))

By Theorem 3, we have y ′ ⊆ yO yB yR, and can repeatedly apply the dec rule for any

y ′j < FV(C(F

′i )), βl (y

′j ) , B. We are left with

y ′O: O,yB : B,y ′

R : R ⊢RC C(F ′i )

where y ′O= [y ∈ yO | y ∈ FV(C(F ′

i ))] (and analogously for y ′R) , thus y

′Oy ′R ⊆ FV(C(F ′

i )),

which allows us to close the goal by the inductive hypothesis.

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 11: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

Counting Immutable Beans - Appendix 11

Case F = let y = proji x ; F′ if βl (x) = O

We need to show

yO : O,yB : B,yR : R ⊢RC let y = proji x ; inc y; O−x (C(F

′))

From βl (x) = O, we have x < yB, so together with yO yB;yR ⊢reuse let y = proji x ; F′, we

have x ∈ yO. Applying Ty-Proj-Own, we are left with

yO : O,y : O,yB : B,yR : R ⊢RC O−x (C(F

′))

If x < FV(C(F ′)), we apply Ty-Dec. In either case, we need to show

y ′O: O,y : O,yB : B,yR : R ⊢RC O

−x (C(F

′))

for some y ′O

⊆ FV(C(F ′)). We also have y ∈ FV(C(F ′)) = FV(F ′) from δreuse, as well asyR ∩ FV (C(F ′)) = yR ∩ FV (C(F )), so we can apply the induction hypothesis.

Case F = let y = proji x ; F′ if βl (x) = B

By Ty-Proj-Bor and the induction hypothesis.

Case F = let y = reset x ; F ′

By Ty-Let, Ty-Reset, and the induction hypothesis.

Case F = let z = c y; F ′

We need to show

yO : O,yB : B,yR : R ⊢RC Capp(y, β(c), let z = c y; C(F′))

We generalize the goal (using yl := bl := []) to

y = yl yr β(c) = bl br | yl |=| bl | y ′O= O(yl )

yO : O,y ′O: O,yB : B,yR : R ⊢RC Capp(yr ,br , let z = c y; O

−(B(yl ),C(F ′)))

where

O(yl ) = OB(yl ) OO(yl )

OB(yl ) = [yli ∈ yl | β(c)i = O ∧ βl (yli ) = B]

OO(yl ) = [yli ∈ yl | β(c)i = O ∧ βl (yli ) = O ∧ (yli ∈ FV(F ′) ∨ ∃j . yli = yj ∧ [j > i ∨ β(c)j = B])]

B(yl ) = [yli ∈ yl | β(c)i = B ∧ βl (yli ) = O ∧ ∄j < i . yli = yj ∧ β(c)j = B]

O and B accurately describe what arguments to increment/decrement in an explicit form:

We increment borrowed references that are passed to an owned parameter, as well as owned

references passed to an owned parameter that

• are still used in F ′,

• are also passed to a borrowed parameter, or

• are also passed to another owned parameter later.

We decrement owned references passed to a borrowed parameter and dead in F ′, but at most

once per variable.

We proceed by parallel induction over yr and br , which, by ⊢pure, have the same length:

Case yr = y ′ y ′r ,br = O b ′r

We need to show

· · · ⊢RC O+y′(y ′r ∪ FV(O−(B(yl ),C(F ′))),Capp(y ′r ,b ′r , let z = c y; O−(B(yl ),C(F ′)))

We see that B(yl y ′) = B(yl ), and that O(yl y ′) is O(yl ) with y ′appended iff

βl (y′) = B ∨ y ′ ∈ FV(F ′) ∨ y ′ ∈ y ′r ∨ y ′ ∈ B(yl )

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 12: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

12 Sebastian Ullrich and Leonardo de Moura

This is exactly the condition for which an inc is inserted, so after conditionally applying

Ty-Inc, we can apply the inner induction hypothesis.

Case yr = y ′ y ′r ,br = B b ′r

We need to show

· · · ⊢RC Capp(y ′r ,b ′r , let z = c y; O−y′(O−(B(yl ),C(F ′))))

We see that O(yl y ′) = O(yl ), and that B(yl y ′) is B(yl ) with y ′appended iff y ′ < B(yl ) ∧

βl (y′) = O. In either case, we have

O−y′(O−(B(yl ),C(F ′))) = O−(B(yl y ′),C(F ′))

and can apply the inner induction hypothesis.

Case yr = [],br = []

We are left to show

yO : O,O(y) : O,yB : B,yR : R ⊢RC let z = c y; O−(B(y),C(F ′))))

We have y ⊆ yO yB by ⊢pure. We thus notice that B(y) is a submultiset of yO and call the

difference list D. We further split D into

D1 = [x ∈ D | x < FV(F ′)]

D2 = [x ∈ D | x ∈ FV(F ′)]

We apply Ty-Let, moving D1 and O(y) into the first goal, temporarily borrowing B(y), andcopying yB into both goals via contraction, leaving us with

D1 : O,yB : B,O(y) : O,B(y) : B ⊢RC c y : O

D2 : O,yB : B,yR : R,B(y) : O, z : O ⊢RC O−(B(y),C(F ′))

For the first goal, we notice that every argument used as a borrowed parameter is in yB orB(y) by ⊢pure, so by weakening we can fulfill them. For arguments used as owned parameters,

we have to pay closer attention to the exact number of hypotheses: We notice that because

yO is distinct, so is D1, so we have covered the first occurrence of every variable dead in F ′

and not in B(y). The missing arguments are by definition exactly O(y), so we are done.

For the second goal, we iteratively apply Ty-Dec and then apply the outer induction

hypothesis: we have D2 ⊆ FV(F ′) by definition, z ∈ FV(F ′) and z < D2 ∪ B(y) by ⊢pure, and

D2 ∩ B(y) = ∅ by definition of the split.

All other application cases are mostly analogous to the constant case (in particular, without

any borrowed parameters). For pap, ⊢β proves the assumption β(c) = O. For reuse, thehypothesis x : R, whose existence is guaranteed by ⊢reuse, additionally has to be moved into

the first goal.

Theorem 10. δRC refines δβ in the pure semantics.

Proof. Trivial, given that the only change is insertion of inc/dec instructions. □

Corollary 1. Suppose c is a parameter-less constant, δ (c) = F .(1) If ⊢ δ (c) ⇓ v , then ⊢ ⟨δRC(c), ∅⟩ ⇓ ⟨l,σ ⟩ and valof(l,σ ) = v .(2) If ⊢ ⟨δRC(c), ∅⟩ ⇓ ⟨l,σ ⟩, then ⊢ δ (c) ⇓ valof(l,σ ).

Proof. By the pure refinement steps (..., Theorem 10), the welltypedness of δRC (Theorem 9),

and the semantics preservation proof of welltyped programs (Theorem 5). □

, Vol. 1, No. 1, Article . Publication date: September 2020.

Page 13: Counting Immutable Beans - Appendix · 2020. 6. 1. · Counting Immutable Beans - Appendix 3 A.3 reset/reuse Definition 3 (Well-formedness of reset/reuse instructions). Reset variables

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

Counting Immutable Beans - Appendix 13

REFERENCESP. N. Benton, Gavin M. Bierman, Valeria de Paiva, and Martin Hyland. 1993. A Term Calculus for Intuitionistic Linear Logic.

In Proceedings of the International Conference on Typed Lambda Calculi and Applications (TLCA ’93). Springer-Verlag,London, UK, UK, 75–90. http://dl.acm.org/citation.cfm?id=645891.671430

Jawahar Chirimar, Carl A. Gunter, and Jon G. Riecke. 1996. Reference counting as a computational interpretation of linear

logic. Journal of Functional Programming 6, 2 (1996), 195–244. https://doi.org/10.1017/S0956796800001660

P. Wadler. 1990. Linear types can change the world!. In IFIP TC 2 Working Conference on Programming Concepts and Methods,Sea of Galilee, Israel (IFIP TC 2), M. Broy and C. Jones (Eds.). North Holland, 347–359.

, Vol. 1, No. 1, Article . Publication date: September 2020.