12
Introspective Pushdown Analysis of Higher-Order Programs Christopher Earl University of Utah [email protected] Ilya Sergey KU Leuven [email protected] Matthew Might University of Utah [email protected] David Van Horn Northeastern University [email protected] Abstract In the static analysis of functional programs, pushdown flow anal- ysis and abstract garbage collection skirt just inside the boundaries of soundness and decidability. Alone, each method reduces analy- sis times and boosts precision by orders of magnitude. This work illuminates and conquers the theoretical challenges that stand in the way of combining the power of these techniques. The challenge in marrying these techniques is not subtle: computing the reachable control states of a pushdown system relies on limiting access dur- ing transition to the top of the stack; abstract garbage collection, on the other hand, needs full access to the entire stack to compute a root set, just as concrete collection does. Introspective pushdown systems resolve this conflict. Introspective pushdown systems pro- vide enough access to the stack to allow abstract garbage collection, but they remain restricted enough to compute control-state reacha- bility, thereby enabling the sound and precise product of pushdown analysis and abstract garbage collection. Experiments reveal syn- ergistic interplay between the techniques, and the fusion demon- strates “better-than-both-worlds” precision. Categories and Subject Descriptors D.3.4 [Programming lan- guages]: Processors—Optimization; F.3.2 [Logics and Meanings of Programs]: Semantics of Programming Languages—Program analysis, Operational semantics General Terms Languages, Theory Keywords CFA2, pushdown systems, abstract interpretation, pushdown analysis, program analysis, abstract machines, abstract garbage collection, higher-order languages 1. Introduction The recent development of a context-free 1 approach to control- flow analysis (CFA2) by Vardoulakis and Shivers has provoked a 1 As in context-free language, not context-sensitivity. Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. ICFP ’12 September 10–12, Copenhagen, Denmark. Copyright c 2012 ACM 978-1-4503-1054-3/12/09. . . $15.00 seismic shift in the static analysis of higher-order programs [22]. Prior to CFA2, a precise analysis of recursive behavior had been a stumbling block—even though flow analyses have an important role to play in optimization for functional languages, such as flow- driven inlining [13], interprocedural constant propagation [19] and type-check elimination [23]. While it had been possible to statically analyze recursion soundly, CFA2 made it possible to analyze recursion precisely by matching calls and returns without approximation. In its pursuit of recursion, clever engineering steered CFA2 just shy of undecidability. The payoff is an order-of-magnitude reduction in analysis time and an order-of-magnitude increase in precision. For a visual measure of the impact, Figure 1 renders the abstract transition graph (a model of all possible traces through the pro- gram) for the toy program in Figure 2. For this example, pushdown analysis eliminates spurious return-flow from the use of recursion. But, recursion is just one problem of many for flow analysis. For instance, pushdown analysis still gets tripped up by the spurious cross-flow problem; at calls to (id f) and (id g) in the previous example, it thinks (id g) could be f or g. Powerful techniques such as abstract garbage collection [14] were developed to solve the cross-flow problem. 2 In fact, abstract garbage collection, by itself, also delivers orders-of-magnitude im- provements to analytic speed and precision. (See Figure 1 again for a visualization of that impact.) It is natural to ask: can abstract garbage collection and pushdown anlysis work together? Can their strengths be multiplied? At first glance, the answer appears to be a disheartening No. 1.1 The problem: The whole stack versus just the top Abstract garbage collections seems to require more than push- down analysis can decidably provide: access to the full stack. Ab- stract garbage collection, like its name implies, discards unreach- able values from an abstract store during the analysis. Like con- crete garbage collection, abstract garbage collection also begins its sweep with a root set, and like concrete garbage collection, it must traverse the abstract stack to compute that root set. But, pushdown 2 The cross-flow problem arises because monotonicity prevents revoking a judgment like “procedure f flows to x,” or “procedure g flows to x,” once it’s been made.

Introspective Pushdown Analysis of Higher-Order Programs

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Introspective Pushdown Analysis of Higher-Order Programs

Introspective Pushdown Analysis of Higher-Order Programs

Christopher EarlUniversity of [email protected]

Ilya SergeyKU Leuven

[email protected]

Matthew MightUniversity of [email protected]

David Van HornNortheastern [email protected]

AbstractIn the static analysis of functional programs, pushdown flow anal-ysis and abstract garbage collection skirt just inside the boundariesof soundness and decidability. Alone, each method reduces analy-sis times and boosts precision by orders of magnitude. This workilluminates and conquers the theoretical challenges that stand in theway of combining the power of these techniques. The challenge inmarrying these techniques is not subtle: computing the reachablecontrol states of a pushdown system relies on limiting access dur-ing transition to the top of the stack; abstract garbage collection,on the other hand, needs full access to the entire stack to computea root set, just as concrete collection does. Introspective pushdownsystems resolve this conflict. Introspective pushdown systems pro-vide enough access to the stack to allow abstract garbage collection,but they remain restricted enough to compute control-state reacha-bility, thereby enabling the sound and precise product of pushdownanalysis and abstract garbage collection. Experiments reveal syn-ergistic interplay between the techniques, and the fusion demon-strates “better-than-both-worlds” precision.

Categories and Subject Descriptors D.3.4 [Programming lan-guages]: Processors—Optimization; F.3.2 [Logics and Meaningsof Programs]: Semantics of Programming Languages—Programanalysis, Operational semantics

General Terms Languages, Theory

Keywords CFA2, pushdown systems, abstract interpretation,pushdown analysis, program analysis, abstract machines, abstractgarbage collection, higher-order languages

1. Introduction

The recent development of a context-free1 approach to control-flow analysis (CFA2) by Vardoulakis and Shivers has provoked a

1 As in context-free language, not context-sensitivity.

Permission to make digital or hard copies of all or part of this work for personal orclassroom use is granted without fee provided that copies are not made or distributedfor profit or commercial advantage and that copies bear this notice and the full citationon the first page. To copy otherwise, to republish, to post on servers or to redistributeto lists, requires prior specific permission and/or a fee.ICFP ’12 September 10–12, Copenhagen, Denmark.Copyright c� 2012 ACM 978-1-4503-1054-3/12/09. . . $15.00

seismic shift in the static analysis of higher-order programs [22].Prior to CFA2, a precise analysis of recursive behavior had beena stumbling block—even though flow analyses have an importantrole to play in optimization for functional languages, such as flow-driven inlining [13], interprocedural constant propagation [19] andtype-check elimination [23].

While it had been possible to statically analyze recursion soundly,CFA2 made it possible to analyze recursion precisely by matchingcalls and returns without approximation. In its pursuit of recursion,clever engineering steered CFA2 just shy of undecidability. Thepayoff is an order-of-magnitude reduction in analysis time and anorder-of-magnitude increase in precision.

For a visual measure of the impact, Figure 1 renders the abstracttransition graph (a model of all possible traces through the pro-gram) for the toy program in Figure 2. For this example, pushdownanalysis eliminates spurious return-flow from the use of recursion.But, recursion is just one problem of many for flow analysis. Forinstance, pushdown analysis still gets tripped up by the spuriouscross-flow problem; at calls to (id f) and (id g) in the previousexample, it thinks (id g) could be f or g.

Powerful techniques such as abstract garbage collection [14]were developed to solve the cross-flow problem.2 In fact, abstractgarbage collection, by itself, also delivers orders-of-magnitude im-provements to analytic speed and precision. (See Figure 1 again fora visualization of that impact.)

It is natural to ask: can abstract garbage collection and pushdownanlysis work together? Can their strengths be multiplied? At firstglance, the answer appears to be a disheartening No.

1.1 The problem: The whole stack versus just the top

Abstract garbage collections seems to require more than push-down analysis can decidably provide: access to the full stack. Ab-stract garbage collection, like its name implies, discards unreach-able values from an abstract store during the analysis. Like con-crete garbage collection, abstract garbage collection also begins itssweep with a root set, and like concrete garbage collection, it musttraverse the abstract stack to compute that root set. But, pushdown

2 The cross-flow problem arises because monotonicity prevents revoking ajudgment like “procedure f flows to x,” or “procedure g flows to x,” onceit’s been made.

Page 2: Introspective Pushdown Analysis of Higher-Order Programs

5

489 110

10

352

368

298

438

485

606

159

440

638

528

497

500

413

289

75

65

174

251

115

436

54221

498 305

363

177

323

142

417

484

85

105181

118

471

491623 291

340

408

68

482

300

549

416

599

427

415

330

454

510

448

72

283

418

432

529

111

609

650

87

255

230

539

351

459

186 163

267

122

564

504

472

56

603

88

26

428

423

464

156 633

253

232 15

356

179

592

399

273

392 145

58

412204

294

295

258

621

573

27

43

370

467

172

55

139

286

194

629

74

541

208

25

254

48

40

474

64

9

649

276

95 39

249

240

496

584

274

384

38377

146

281

112

512 559

557

92

369 414

138

234

543

278

316

430

506

594

456

83

513

589

104 262

372

598

619 488

50

596

405

320

98

35

109

522

315588

271

509

170

33 376

580

530

307 532

221

100

457 335

394

540

150

28

133

79

350

480

569

410 555

302

439

515402

259

534

17

81

476 466

12 333 125

225

419 23

154

8

196

525 157

337

309 153

135

590

365

113

561

446

176

581

16

89 426

210

630

451

444

386

13

344

398

54

453

407

76

460

84

263

136

567

80445 44

473

198

642

239

31

469

188

483

293

67

492

243

160

385

166

576

134

244

217

390

62

357

63

206

420

610

463

167

199

130

508

306

635

292

620

563

526

103

441

458 252

301

568

314

325

209

601

625

324

646

20

334

637

347

583

173

403 618

317

24

175 631

371

189

443

216

241

147

213

218

148

575

479

571

587

536

477

161

553

358

193

425

36

1322

636195

628

182

223 319

570

22

331

535

282 158 220

32

364

236

343

257

341

106

180

151

643

256

184

144

353

37

475

648

516 359

411

465

137 214

275551

612

389

634

231

595

442

523

141

222

395

593

116

229

577

52

361

602

219 277

86

164

242

49 490

73 129

268

332

565

378

578

131

582 328 197

632

552

387

579 297

380

211

354

124

126

502191 82

59

120

264

269

360287

520

19

270

183

152

501

514

97

202

207 391

336 493

1434

107

279

117 201

546

227

641

121

162

299

645

462

51

91

192

30

149

586

310

499

3226

355

409

547

247 171

450

422

128

560

615 447

470

200

327

400

627

42

228

397

94

101

434 19034

290

626

93

521

311

78

519 266

169

393

455 527

250

304

401

550

61

71

248

622 102

600

468

373

265

375

272

313

537 348

235

29

524

381

90

404

435

494

545 303

11

345

168

280

46

6

461 639

487

424

339

308

114

329

346

362

203

205

486

18

284

245

437 342 288

233

7 605

155

41

238

349

585

99

604

538 617 544

66 591

548

431 224

165 367

108 246

614

433

1

478

388

312

187

260

396

607

644 322 70

406

374

53

96

45 47

562

507

237

318

185

558 140

296

481

533

127

38

321

503

647

574

366

69 379 597

624

377

382

554

518 119

531

495

505

429

608

452 123

556

60

511

640

611

178

14

212

572

261

215

613

517 421

326

57

616

566

338

449

285

(1) without pushdown analysis or abstract GC: 653 states

138 44

127

24

34

64

15

16 123

48

110

58

125 53 103

87 107

9

12

122

6

13

36

28

10

93

129 25

31 89

130

18 20 66

33

30

14

95 139 49

3

51 132

52

91

108 11 99

86

39

4075

113

17

135

21111

50 84

57 124

85

60

45 121 1

77

59112

105 4

8

120 128 73

90

13668

27

134

101

92 88 6576 4726

133 115

126

46 35

81

2269

43 80

119

98

116

61 79

109

104

78

67

29

13783

117

41

38

74

7

100

106

5582

32

114

96

63

19

97

70 94

23

2

72

56

42

11862

131

537

71

102

54

(2) with pushdown only: 139 states

54 764

78

85

82

32

29 66 42

63 83

17

53 58 45

60 62

31

16

23

59

65

34

9 51

33

4677

92

19 102

41 103 47

91

38

1 70

3 84

104

50

36

10

26

35 27

96

528

8 15 64

80

71

14

88

55

74

43

105 87 61

22

86

25 56 39

44 24

48 81 79

57

7

67 37

98 13

97

72

89

69

101

6

52 73

21

40

100

75

268

12 18 11

20

90 30

94

49 99 93

95

(3) with GC only: 105 states

28 76

59

32

13

27

61

21

45

49

4

44 46 6

1 71

70 65 185 7 36

67

6025

43

19 15

50

3 34

73

14

20 52

38 4130

68

54 51 3542 22

2 11 23

72 66

26

2431 64

39

69

33

48

56 75

40 77

53

12

29

58

1017

8 47

63

955

74

37 62

57 16

(4) with pushdown analysis and abstract GC: 77 states

Figure 1. We generated an abstract transition graph for the sameprogram from Figure 2 four times: (1) without pushdown analysisor abstract garbage collection; (2) with only abstract garbage col-lection; (3) with only pushdown analysis; (4) with both pushdownanalysis and abstract garbage collection. With only pushdown orabstract GC, the abstract transition graph shrinks by an order ofmagnitude, but in different ways. The pushdown-only analysis isconfused by variables that are bound to several different higher-order functions, but for short durations. The abstract-GC-only isconfused by non-tail-recursive loop structure. With both techniquesenabled, the graph shrinks by nearly half yet again and fully recov-ers the control structure of the original program.

(define (id x) x)

(define (f n)

(cond [(<= n 1) 1]

[else (* n (f (- n 1)))]))

(define (g n)

(cond [(<= n 1) 1]

[else (+ (* n n) (g (- n 1)))]))

(print (+ ((id f) 3) ((id g) 4)))

Figure 2. A small example to illuminate the strengths and weak-nesses of both pushdown analysis and abstract garbage collection.

systems are restricted to viewing the top of the stack (or a boundeddepth)—a condition violated by this traversal.

Fortunately, abstract garbage collection does not need to arbitrarilymodify the stack. In fact, it does not even need to know the order ofthe frames; it only needs the set of frames on the stack. We find aricher class of machine—introspective pushdown systems—whichretains just enough restrictions to compute reachable control states,yet few enough to enable abstract garbage collection.

It is therefore possible to fuse the full benefits of abstract garbagecollection with pushdown analysis. The dramatic reduction in ab-stract transition graph size from the top to the bottom in Figure 1(and echoed by later benchmarks) conveys the impact of this fusion.

Secondary motivations There are three strong secondary motiva-tions for this work: (1) bringing context-sensitivity to pushdownanalysis; (2) exposing the context-freedom of the analysis; and (3)enabling pushdown analysis without continuation passing style.

In CFA2, monovariant (0CFA-like) context-sensitivity is etcheddirectly into the abstract semantics, which are in turn, phrased interms of an explicit (imperative) summarization algorithm for apartitioned continuation-passing style.

In addition, the context-freedom of the analysis is buried implicitlyinside this algorithm. No pushdown system or context-free gram-mar is explicitly identified. A necessary precursor to our work wasto make the pushdown system in CFA2 explicit.

A third motivation was to show that a transformation to continuation-passing style is unnecessary for pushdown analysis. In fact, push-down analysis is arguably more natural over direct-style programs.

1.2 Overview

We first review preliminaries to set a consistent feel for terminologyand notation, particularly with respect to pushdown systems. Thederivation of the analysis begins with a concrete CESK-machine-style semantics for A-Normal Form �-calculus. The next step is aninfinite-state abstract interpretation, constructed by bounding theC(ontrol), E(nvironment) and S(tore) portions of the machine whileleaving the stack—the K(ontinuation)—unbounded. A simple shiftin perspective reveals that this abstract interpretation is a rootedpushdown system.

We then introduce abstract garbage collection and quickly find thatit violates the pushdown model with its traversals of the stack. Toprove the decidability of control-state reachability, we formulate in-trospective pushdown systems, and recast abstract garbage collec-

Page 3: Introspective Pushdown Analysis of Higher-Order Programs

tion within this framework. We then show that control-state reach-ability is decidable for introspective pushdown systems as well.

We conclude with an implementation and empirical evaluation thatshows strong synergies between pushdown analysis and abstractgarbage collection, including significant reductions in the size ofthe abstract state transition graph.

1.3 Contributions

We make the following contributions:

1. Our primary contribution is demonstrating the decidability offusing abstract garbage collection with pushdown flow analysisof higher-order programs. Proof comes in the form of a fixed-point solution for computing the reachable control-states of anintrospective pushdown system and an embedding of abstractgarbage collection as an introspective pushdown system.

2. We show that classical notions of context-sensitivity, such ask-CFA and poly/CFA, have direct generalizations in a push-down setting: monovariance3 is not an essential restriction, asin CFA2.

3. We make the context-free aspect of CFA2 explicit: we clearlydefine and identify the pushdown system. We do so by startingwith a classical CESK machine and systematically abstractinguntil a pushdown system emerges. We also remove the orthogo-nal frame-local-bindings aspect of CFA2, so as to directly solelyon the pushdown nature of the analysis.

4. We remove the requirement for CPS-conversion by synthesiz-ing the analysis directly for direct-style (in the form of A-normal form lambda-calculus).

5. We empirically validate claims of improved precision on a suiteof benchmarks. We find synergies between pushdown analysisand abstract garbage collection that makes the whole greaterthat the sum of its parts.

2. Pushdown preliminaries

The literature contains many equivalent definitions of pushdownmachines, so we adapt our own definitions from Sipser [20]. Read-ers familiar with pushdown theory may wish to skip ahead.

2.1 Syntactic sugar

When a triple (x, `, x0) is an edge in a labeled graph:

x`⇢x0 ⌘ (x, `, x0

).

Similarly, when a pair (x, x0) is a graph edge:

x ⇢ x0 ⌘ (x, x0).

We use both string and vector notation for sequences:

a1a2 . . . an ⌘ ha1, a2, . . . , ani ⌘ ~a.

2.2 Stack actions, stack change and stack manipulation

Stacks are sequences over a stack alphabet �. To reason about stackmanipulation concisely, we first turn stack alphabets into “stack-

3 Monovariance refers to an abstraction that groups all bindings to the samevariable together: there is one abstract variant for all bindings to eachvariable.

action” sets; each character represents a change to the stack: push,pop or no change.

For each character � in a stack alphabet �, the stack-action set �±contains a push character �+; a pop character ��; and a no-stack-change indicator, ✏:

g 2 �± ::= ✏ [stack unchanged]| �+ for each � 2 � [pushed �]| �� for each � 2 � [popped �].

In this paper, the symbol g represents some stack action.

When we develop introspective pushdown systems, we are goingto need formalisms for easily manipulating stack-action strings andstacks. Given a string of stack actions, we can compact it into aminimal string describing net stack change. We do so through theoperator b·c : �

⇤± ! �

⇤±, which cancels out opposing adjacent

push-pop stack actions:

b~g �+�� ~g 0c = b~g ~g 0c b~g ✏ ~g 0c = b~g ~g 0c,

so that b~gc = ~g, if there are no cancellations to be made in thestring ~g.

We can convert a net string back into a stack by stripping off thepush symbols with the stackify operator, d·e : �⇤

± * �

⇤:

d�+�0+ . . . �

(n)+ e = h�(n), . . . , �0, �i,

and for convenience, [~g] = db~gce. Notice the stackify operator isdefined for strings containing only push actions.

2.3 Pushdown systems

A pushdown system is a triple M = (Q,�, �) where:

1. Q is a finite set of control states;2. � is a stack alphabet; and3. � ✓ Q⇥ �± ⇥Q is a transition relation.

The set Q⇥�

⇤ is called the configuration-space of this pushdownsystem. We use PDS to denote the class of all pushdown systems.

For the following definitions, let M = (Q,�, �).

• The labeled transition relation ( 7�!M ) ✓ (Q⇥ �

⇤)⇥ �± ⇥

(Q⇥�

⇤) determines whether one configuration may transition

to another while performing the given stack action:

(q,~�)✏7�!M

(q0,~�) iff q✏⇢ q0 2 � [no change]

(q, � : ~�)��7�!M

(q0,~�) iff q��⇢ q0 2 � [pop]

(q,~�)�+7�!M

(q0, � : ~�) iff q�+⇢ q0 2 � [push].

• If unlabelled, the transition relation ( 7�!) checks whether anystack action can enable the transition:

c 7�!M

c0 iff c g7�!M

c0 for some stack action g.

• For a string of stack actions g1 . . . gn:

c0g1...gn7�!

Mcn iff c0

g17�!M

c1g27�!M

· · ·gn�17�!M

cn�1gn7�!M

cn,

for some configurations c0, . . . , cn.

Page 4: Introspective Pushdown Analysis of Higher-Order Programs

• For the transitive closure:

c⇤7�!M

c0 iff c ~g7�!M

c0 for some action string ~g .

2.4 Rooted pushdown systems

A rooted pushdown system is a quadruple (Q,�, �, q0) in which(Q,�, �) is a pushdown system and q0 2 Q is an initial (root) state.RPDS is the class of all rooted pushdown systems.

For a rooted pushdown system M = (Q,�, �, q0), we define thereachable-from-root transition relation:

cg7�!�!M

c0 iff (q0, hi) ⇤7�!M

c and cg7�!M

c0.

In other words, the root-reachable transition relation also makessure that the root control state can actually reach the transition.

We overload the root-reachable transition relation to operate oncontrol states:

qg7�!�!M

q0 iff (q,~�) g7�!�!M

(q0,~� 0) for some stacks ~�,~� 0.

For both root-reachable relations, if we elide the stack-action label,then, as in the un-rooted case, the transition holds if there existssome stack action that enables the transition:

q 7�!�!M

q0 iff q g7�!�!M

q0 for some action g.

2.5 Computing reachability in pushdown systems

A pushdown flow analysis can be construed as computing the root-reachable subset of control states in a rooted pushdown system,M = (Q,�, �, q0):

n

q : q0 7�!�!M

qo

Reps et. al and many others provide a straightforward “summariza-tion” algorithm to compute this set [1, 8, 17, 18]. Our preliminaryreport also offers a reachability algorithm tailored to higher-orderprograms [4].

2.6 Nondeterministic finite automata

In this work, we will need a finite description of all possible stacksat a given control state within a rooted pushdown system. We willexploit the fact that the set of stacks at a given control point is aregular language. Specifically, we will extract a nondeterministicfinite automaton accepting that language from the structure of arooted pushdown system. A nondeterministic finite automaton(NFA) is a quintuple M = (Q,⌃, �, q0, F ):

• Q is a finite set of control states;•⌃ is an input alphabet;

• � ✓ Q⇥ (⌃ [ {✏})⇥Q is a transition relation.• q0 is a distinguished start state.• F ✓ Q is a set of accepting states.

We denote the class of all NFAs as NFA.

3. Setting: A-Normal Form �-calculus

Since our goal is analysis of higher-order languages, we operate onthe �-calculus. To simplify presentation of the concrete and abstract

c 2 Conf = Exp⇥ Env ⇥ Store ⇥Kont [configurations]⇢ 2 Env = Var * Addr [environments]

� 2 Store = Addr ! Clo [stores]clo 2 Clo = Lam⇥ Env [closures] 2 Kont = Frame

⇤ [continuations]� 2 Frame = Var ⇥ Exp⇥ Env [stack frames]a 2 Addr is an infinite set of addresses [addresses].

Figure 3. The concrete configuration-space.

semantics, we choose A-Normal Form �-calculus. (This is a strictlycosmetic choice: all of our results can be replayed mutatis mutandisin the standard direct-style setting as well.) ANF enforces an orderof evaluation and it requires that all arguments to a function beatomic:

e 2 Exp ::= (let ((v call)) e) [non-tail call]| call [tail call]| æ [return]

f,æ 2 Atom ::= v | lam [atomic expressions]lam 2 Lam ::= (� (v) e) [lambda terms]call 2 Call ::= (f æ) [applications]

v 2 Var is a set of identifiers [variables].

We use the CESK machine of Felleisen and Friedman [5] to specifya small-step semantics for ANF. The CESK machine has an explicitstack, and under a structural abstraction, the stack component ofthis machine directly becomes the stack component of a pushdownsystem. The set of configurations (Conf ) for this machine has thefour expected components (Figure 3).

3.1 Semantics

To define the semantics, we need five items:

1. I : Exp ! Conf injects an expression into a configuration:

c0 = I(e) = (e, [], [], hi).

2. A : Atom⇥Env⇥Store * Clo evaluates atomic expressions:

A(lam, ⇢,�) = (lam, ⇢) [closure creation]A(v, ⇢,�) = �(⇢(v)) [variable look-up].

3. ()) ✓ Conf ⇥ Conf transitions between configurations.(Defined below.)

4. E : Exp ! P (Conf ) computes the set of reachable machineconfigurations for a given program:

E(e) = {c : I(e) )⇤ c} .

5. alloc : Var ⇥ Conf ! Addr chooses fresh store addressesfor newly bound variables. The address-allocation function isan opaque parameter in this semantics, so that the forthcom-ing abstract semantics may also parameterize allocation. Thisparameterization provides the knob to tune the polyvarianceand context-sensitivity of the resulting analysis. For the sakeof defining the concrete semantics, letting addresses be naturalnumbers suffices, and then the allocator can choose the lowest

Page 5: Introspective Pushdown Analysis of Higher-Order Programs

unused address:

Addr = Nalloc(v, (e, ⇢,�,)) = 1 +max(dom(�)).

Transition relation To define the transition c ) c0, we need threerules. The first rule handle tail calls by evaluating the function intoa closure, evaluating the argument into a value and then moving tothe body of the closure’s �-term:

cz }| {

([[(f æ)]], ⇢,�,) )

c0z }| {

(e, ⇢00,�0,) , where([[(� (v) e)]], ⇢0) = A(f, ⇢,�)

a = alloc(v, c)

⇢00 = ⇢0[v 7! a]

�0= �[a 7! A(æ, ⇢,�)].

Non-tail call pushes a frame onto the stack and evaluates the call:c

z }| {

([[(let ((v call)) e)]], ⇢,�,) )

c0z }| {

(call , ⇢,�, (v, e, ⇢) : ) .

Function return pops a stack frame:c

z }| {

(æ, ⇢,�, (v, e, ⇢0) : ) )

c0z }| {

(e, ⇢00,�0,) , wherea = alloc(v, c)

⇢00 = ⇢0[v 7! a]

�0= �[a 7! A(æ, ⇢,�)].

4. Pushdown abstract interpretation

Our first step toward a static analysis is an abstract interpretationinto an infinite state-space. To achieve a pushdown analysis, wesimply abstract away less than we normally would. Specifically,we leave the stack height unbounded.

Figure 4 details the abstract configuration-space. To synthesize it,we force addresses to be a finite set, but crucially, we leave thestack untouched. When we compact the set of addresses into afinite set, the machine may run out of addresses to allocate, andwhen it does, the pigeon-hole principle will force multiple closuresto reside at the same address. As a result, we have no choicebut to force the range of the store to become a power set in theabstract configuration-space. The abstract transition relation hascomponents analogous to those from the concrete semantics:

Program injection The abstract injection function ˆI : Exp !\Conf pairs an expression with an empty environment, an emptystore and an empty stack to create the initial abstract configuration:

c0 =

ˆI(e) = (e, [], [], hi).

Atomic expression evaluation The abstract atomic expressionevaluator, ˆA : Atom⇥ d

Env ⇥\Store ! P(

d

Clo), returns the valueof an atomic expression in the context of an environment and astore; it returns a set of abstract closures:

ˆA(lam, ⇢, �) = {(lam, ⇢)} [closure creation]ˆA(v, ⇢, �) = �(⇢(v)) [variable look-up].

c 2 \Conf = Exp⇥ d

Env ⇥\Store ⇥ [

Kont [configurations]

⇢ 2 d

Env = Var * [Addr [environments]

� 2 \Store =

[Addr ! P

d

Clo

[stores]

c

clo 2 d

Clo = Lam⇥ d

Env [closures]

2 [Kont =

\Frame

⇤[continuations]

ˆ� 2 \Frame = Var ⇥ Exp⇥ d

Env [stack frames]

a 2 [Addr is a finite set of addresses [addresses].

Figure 4. The abstract configuration-space.

Reachable configurations The abstract program evaluator ˆE :

Exp ! P(

\Conf ) returns all of the configurations reachable from

the initial configuration:

ˆE(e) =n

c : ˆI(e) ;⇤ co

.

Because there are an infinite number of abstract configurations, anaıve implementation of this function may not terminate.

Transition relation The abstract transition relation (;) ✓\Conf ⇥ \

Conf has three rules, one of which has become non-deterministic. A tail call may fork because there could be multipleabstract closures that it is invoking:

cz }| {

([[(f æ)]], ⇢, �, ) ;

c0z }| {

(e, ⇢00, �0, ) , where

([[(� (v) e)]], ⇢0) 2 ˆA(f, ⇢, �)

a =

[alloc(v, c)⇢00 = ⇢0[v 7! a]

�0= � t [a 7! ˆA(æ, ⇢, �)].

We define all of the partial orders shortly, but for stores:

(� t �0)(a) = �(a) [ �0

(a).

A non-tail call pushes a frame onto the stack and evaluates the call:c

z }| {

([[(let ((v call)) e)]], ⇢, �, ) ;

c0z }| {

(call , ⇢, �, (v, e, ⇢) : ) .

A function return pops a stack frame:c

z }| {

(æ, ⇢, �, (v, e, ⇢0) : ) ;

c0z }| {

(e, ⇢00, �0, ) , where

a =

[alloc(v, c)⇢00 = ⇢0[v 7! a]

�0= � t [a 7! ˆA(æ, ⇢, �)].

Allocation: Polyvariance and context-sensitivity In the abstractsemantics, the abstract allocation function [alloc : Var ⇥ \

Conf ![Addr determines the polyvariance of the analysis. In a control-flow analysis, polyvariance literally refers to the number of abstractaddresses (variants) there are for each variable. An advantage ofthis framework over CFA2 is that varying this abstract allocationfunction instantiates pushdown versions of classical flow analyses.All of the following allocation approaches can be used with the

Page 6: Introspective Pushdown Analysis of Higher-Order Programs

abstract semantics. The abstract allocation function is a parameterto the analysis.

Monovariance: Pushdown 0CFA Pushdown 0CFA uses vari-ables themselves for abstract addresses:

[Addr = Var

alloc(v, c) = v.

Context-sensitive: Pushdown 1CFA Pushdown 1CFA pairs thevariable with the current expression to get an abstract address:

[Addr = Var ⇥ Exp

alloc(v, (e, ⇢, �, )) = (v, e).

Polymorphic splitting: Pushdown poly/CFA Assuming we com-piled the program from a programming language with let-boundpolymorphism and marked which functions were let-bound, we canenable polymorphic splitting:

[Addr = Var + Var ⇥ Exp

alloc(v, ([[(f æ)]], ⇢, �, )) =

(

(v, [[(f æ)]]) f is let-boundv otherwise.

Pushdown k-CFA For pushdown k-CFA, we need to look beyondthe current state and at the last k states. By concatenating theexpressions in the last k states together, and pairing this sequencewith a variable we get pushdown k-CFA:

[Addr = Var ⇥ Exp

k

[alloc(v, h(e1, ⇢1, �1, 1), . . .i) = (v, he1, . . . , eki).

4.1 Partial orders

For each set ˆX inside the abstract configuration-space, we use thenatural partial order, (vX) ✓ ˆX ⇥ ˆX . Abstract addresses andsyntactic sets have flat partial orders. For the other sets, the partialorder lifts:

• point-wise over environments:

⇢ v ⇢0 iff ⇢(v) = ⇢0(v) for all v 2 dom(⇢);

• component-wise over closures:

(lam, ⇢) v (lam, ⇢0) iff ⇢ v ⇢0;

• point-wise over stores:

� v �0 iff �(a) v �0(a) for all a 2 dom(�);

• component-wise over frames:

(v, e, ⇢) v (v, e, ⇢0) iff ⇢ v ⇢0;

• element-wise over continuations:

hˆ�1, . . . , ˆ�ni v hˆ�01, . . . , ˆ�

0ni iff ˆ�i v ˆ�0

i; and

• component-wise across configurations:

(e, ⇢, �, ) v (e, ⇢0, �0, 0) iff ⇢ v ⇢0 and � v �0 and v 0.

4.2 Soundness

To prove soundness, an abstraction map ↵ connects the concreteand abstract configuration-spaces:

↵(e, ⇢,�,) = (e,↵(⇢),↵(�),↵())

↵(⇢) = �v.↵(⇢(v))

↵(�) = �a.G

↵(a)=a

{↵(�(a))}

↵h�1, . . . ,�ni = h↵(�1), . . . ,↵(�n)i↵(v, e, ⇢) = (v, e,↵(⇢))

↵(a) is determined by the allocation functions.

It is then easy to prove that the abstract transition relation simulatesthe concrete transition relation:

Theorem 4.1. If:

↵(c) v c and c ) c0,

then there must exist c0 2 \Conf such that:

↵(c0) v c0 and c ; c0.

Proof. The proof follows by case-wise analysis on the type of theexpression in the configuration. It is a straightforward adaptation ofsimilar proofs, such as that of [11] for k-CFA.

5. The shift: From abstract CESK to rooted PDS

In the previous section, we constructed an infinite-state abstractinterpretation of the CESK machine. The infinite-state nature of theabstraction makes it difficult to see how to answer static analysisquestions. Consider, for instance, a control flow-question:

At the call site (f æ), may a closure over lam be called?

If the abstracted CESK machine were a finite-state machine, analgorithm could answer this question by enumerating all reach-able configurations and looking for an abstract configuration([[(f æ)]], ⇢, �, ) in which (lam, ) 2 ˆA(f, ⇢, �). However, be-cause the abstracted CESK machine may contain an infinite numberof reachable configurations, enumeration is not an option.

Fortunately, a shift in perspective reveals the abstracted CESKmachine to be a rooted pushdown system. This shift permits theuse of a control-state reachability algorithm in place of exhaustivesearch of the configuration-space. In this shift, a control-state isan expression-environment-store triple, and a stack character is aframe. Figure 5 defines the program-to-RPDS conversion function[PDS : Exp ! RPDS.

At this point, we can compute the root-reachable control statesusing a straightforward summarization algorithm [1, 17, 18]. Thisis the essence of CFA2.

6. Introspection for abstract garbage collection

Abstract garbage collection [14] yields large improvements in pre-cision by using the abstract interpretation of garbage collection tomake more efficient use of the finite address space available duringanalysis. Because of the way abstract garbage collection operates, it

Page 7: Introspective Pushdown Analysis of Higher-Order Programs

[PDS(e) = (Q,�, �, q0), where

Q = Exp⇥ d

Env ⇥\Store

� =

\Frame

(q, ✏, q0) 2 � iff (q, ) ; (q0, ) for all

(q, ˆ��, q0) 2 � iff (q, ˆ� : ) ; (q0, ) for all

(q, ˆ�0+, q

0) 2 � iff (q, ) ; (q0, ˆ�0

: ) for all

(q0, hi) = ˆI(e).

Figure 5. [PDS : Exp ! RPDS.

grants exact precision to the flow analysis of variables whose bind-ings die between invocations of the same abstract context. Becausepushdown analysis grants exact precision in tracking return-flow,it is clearly advantageous to combine these techniques. Unfortu-nately, as we shall demonstrate, abstract garbage collection breaksthe pushdown model by requiring full stack inspection to discoverthe root set.

Abstract garbage collection modifies the transition relation to con-duct a “stop-and-copy” garbage collection before each transition.To do this, we define a garbage collection function ˆG :

\Conf !

\Conf on configurations:

ˆG(

cz }| {

e, ⇢, �, ) = (e, ⇢, �|Reachable(c), ),

where the pipe operation f |S yields the function f , but with inputsnot in the set S mapped to bottom—the empty set. The reachabilityfunction Reachable :

\Conf ! P(

[Addr) first computes the

root set, and then the transitive closure of an address-to-addressadjacency relation:

Reachable(

cz }| {

e, ⇢, �, ) =n

a : a0 2 Root(c) and a0⇤_�

ao

,

where the function Root :

\Conf ! P(

[Addr) finds the root

addresses:

Root(e, ⇢, �, ) = range(⇢) [ StackRoot(),

and the StackRoot : [Kont ! P(

[Addr) function finds roots down

the stack:

StackRooth(v1, e1, ⇢1), . . . , (vn, en, ⇢n)i =[

i

range(⇢i),

and the relation (_) ✓ [Addr ⇥ \

Store ⇥ [Addr connects adjacent

addresses:

a _�

a0 iff there exists (lam, ⇢) 2 �(a) such that a0 2 range(⇢).

The new abstract transition relation is thus the composition ofabstract garbage collection with the old transition relation:

(;GC) = (;) � ˆG

Problem: Stack traversal violates pushdown constraint In theformulation of pushdown systems, the transition relation is re-stricted to looking at the top frame, and even in less restricted for-mulations, at most a bounded number of frames can be inspected.Thus, the relation (;GC) cannot be computed as a straightforwardpushdown analysis using summarization.

Solution: Introspective pushdown systems To accomodate thericher structure of the relation (;GC), we now define introspec-tive pushdown systems. Once defined, we can embed the garbage-collecting abstract interpretation within this framework, and thenfocus on developing a control-state reachability algorithm for thesesystems.

An introspective pushdown system is a quadruple M = (Q,�, �, q0):

1. Q is a finite set of control states;2. � is a stack alphabet;3. � ✓ Q⇥ �

⇤ ⇥ �± ⇥Q is a transition relation; and4. q0 is a distinguished root control state.

The second component in the transition relation is a realizable stackat the given control-state. This realizable stack distinguishes anintrospective pushdown system from a general pushdown system.IPDS denotes the class of all introspective pushdown systems.

Determining how (or if) a control state q transitions to a controlstate q0, requires knowing a path taken to the state q. Thus, weneed to define reachability inductively. When M = (Q,�, �, q0),transition from the initial control state considers only empty stacks:

q0g7�!�!M

q iff (q0, hi, g, q) 2 �.

For non-root states, the paths to that state matter, since they deter-mine the stacks realizable with that state:

qg7�!�!M

q0 iff there exists ~g such that q0~g7�!�!M

q and (q, [~g], g, q0) 2 �,

where qhg1,...,gni7�!�!

Mq0 iff q g17�!�!

Mq1

g27�!�!M

· · · gn7�!�!M

q0.

6.1 Garbage collection in introspective pushdown systems

To convert the garbage-collecting, abstracted CESK machine intoan introspective pushdown system, we use the function \IPDS :

Exp ! IPDS:

\IPDS(e) = (Q,�, �, q0)

Q = Exp⇥ d

Env ⇥\Store

� =

\Frame

(q, , ✏, q0) 2 � iff ˆG(q, ) ; (q0, )

(q, ˆ� : , ˆ��, q0) 2 � iff ˆG(q, ˆ� : ) ; (q0, )

(q, , ˆ�+, q0) 2 � iff ˆG(q, ) ; (q0, ˆ� : )

(q0, hi) = ˆI(e).

7. Introspective reachability via Dyck stategraphs

Having defined introspective pushdown systems and embedded ourabstract, garbage-collecting semantics within them, we are ready todefine control-state reachability for IDPSs.

We cast our reachability algorithm for introspective pushdown sys-tems as finding a fixed-point, in which we incrementally accrete thereachable control states into a “Dyck state graph.”

A Dyck state graph is a quadruple G = (S,�, E, s0), in which:

Page 8: Introspective Pushdown Analysis of Higher-Order Programs

1. S is a finite set of nodes;2. � is a set of frames;3. E ✓ S ⇥ �± ⇥ S is a set of stack-action edges; and4. s0 is an initial state;

such that for any node s 2 S, it must be the case that:

(s0, hi) ⇤7�!G

(s,~�) for some stack ~�.

In other words, a Dyck state graph is equivalent to a rooted push-down system in which there is a legal path to every control statefrom the initial control state.4 We use DSG to denote the class ofDyck state graphs. (Clearly, DSG ⇢ RPDS.)

Our goal is to compile an implicitly-defined introspective push-down system into an explicited-constructed Dyck state graph. Dur-ing this transformation, the per-state path considerations of an in-trospective pushdown are “baked into” the Dyck state graph. Wecan formalize this compilation process as a map, DSG : IPDS !DSG.

Given an introspective pushdown system M = (Q,�, �, q0), itsequivalent Dyck state graph is DSG(M) = (S,�, E, q0), wheres0 = q0, the set S contains reachable nodes:

S =

n

q : q0~g7�!�!M

q for some stack-action sequence ~go

,

and the set E contains reachable edges:

E =

n

qg⇢ q0 : q

g7�!�!M

q0o

.

Our goal is to find a method for computing a Dyck state graph froman introspective pushdown system.

7.1 Compiling to Dyck state graphs

We now turn our attention to compiling an introspective pushdownsystem (defined implicitly) into a Dyck state graph (defined explic-itly). That is, we want an implementation of the function DSG. Todo so, we first phrase the Dyck state graph construction as the leastfixed point of a monotonic function. This formulation provides astraightforward iterative method for computing the function DSG.

The function F : IPDS ! (DSG ! DSG) generates the mono-tonic iteration function we need:

F(M) = f , whereM = (Q,�, �, q0)

f(S,�, E, s0) = (S0,�, E0, s0), where

S0= S [

n

s0 : s 2 S and s 7�!�!M

s0o

[ {s0}

E0= E [

n

sg⇢ s0 : s 2 S and s

g7�!�!M

s0o

.

Given an introspective pushdown system M , each application ofthe function F(M) accretes new edges at the frontier of the Dyckstate graph.

4 We chose the term Dyck state graph because the sequences of stackactions along valid paths through the graph correspond to substrings inDyck languages. A Dyck language is a language of balanced, “colored”parentheses. In this case, each character in the stack alphabet is a color.

7.2 Computing a round of F

The formalism obscures an important detail in the computationof an iteration: the transition relation ( 7�!�!) for the introspectivepushdown system must compute all possible stacks in determiningwhether or not there exists a transition. Fortunately, this is not asonerous as it seems: the set of all possible stacks for any givencontrol-point is a regular language, and the finite automaton thatencodes this language can be lifted (or read off) the structure ofthe Dyck state graph. The function Stacks : DSG ! S ! NFAperforms exactly this extraction:

Stacks(

Mz }| {

S,�, E, s0)(s) = (S,�, �, s0, {s}), where(s0, �, s00) 2 � if (s0, �+, s00) 2 E

(s0, ✏, s00) 2 � if s0 ~g7�!�!M

s00 and [~g] = ✏.

7.3 Correctness

Once the algorithm reaches a fixed point, the Dyck state graph iscomplete:

Theorem 7.1. DSG(M) = lfp(F(M)).

Proof. Let M = (Q,�, �, q0). Let f = F(M). Observe thatlfp(f) = fn

(;,�, ;, q0) for some n. When N ✓ M , then it easyto show that f(N) ✓ M . Hence, DSG(M) ◆ lfp(F(M)).

To show DSG(M) ✓ lfp(F(M)), suppose this is not the case.Then, there must be at least one edge in DSG(M) that is notin lfp(F(M)). By the defintion of DSG(M), each edge must bepart of a sequence of edges from the initial state. Let (s, g, s0) bethe first edge in its sequence from the initial state that is not inlfp(F(M). Because the proceeding edge is in lfp(F(M)), the states is in lfp(F(M)). Let m be the lowest natural number such that sappears in fm

(M). By the definition of f , this edge must appear infm+1

(M), which means it must also appear in lfp(F(M)), whichis a contradiction. Hence, DSG(M) ✓ lfp(F(M)).

7.4 Complexity

While decidability is the goal, it is straightforward to determinethe complexity of this naıve fixed-point method. To determine thecomplexity of this algorithm, we ask two questions: how manytimes would the algorithm invoke the iteration function in the worstcase, and how much does each invocation cost in the worst case?The size of the final Dyck state graph bounds the run-time of thealgorithm. Suppose the final Dyck state graph has m states. In theworst case, the iteration function adds only a single edge each time.Between any two states, there is one ✏-edge, one push edge, orsome number of pop edges (at most |�|). Since there are at most|�|m2 edges in the final graph, the maximum number of iterationsis |�|m2.

The cost of computing each iteration is harder to bound. The costof determining whether to add a push edge is constant, as is the costof adding an ✏-edge. So the cost of determining all new push edgesand new ✏-edges to add is constant. Determining whether or not toadd a pop edge is expensive. To add the pop edge s ⇢�� s0, wemust prove that there exists a configuration-path to the control states, in which the character � is on the top of the stack. This reducesto a CFL-reachability query [9] at each node, the cost of which isO(|�±|3m3

) [8].

Page 9: Introspective Pushdown Analysis of Higher-Order Programs

To summarize, in terms of the number of reachable control states,the complexity of this naive algorithm is:

O((|�|m2)⇥ (|�±|3m3

)) = O(|�|4m5).

(As with summarization, it is possible to maintain a work-list andintroduce an ✏-closure graph to avoid spurious recomputation. Thisultimately reduces complexity to O(|�|2m4

).)

8. Implementation and evaluation

We have developed an implementation to produce the Dyck stategraph of an introspective pushdown system. While the fixed-pointcomputation 7.2 could be rendered directly as functional code, ex-tending the classical summarization-based algorithm for pushdownreachability to introspective pushdown systems yields better per-formance. In this section we present a variant of such an algorithmand discuss results from an implementation that can analyze a largesubset of the Scheme programming language.

8.1 Iterating over a DSG: An implementor’s view

To synthesize a Dyck state graph from an introspective pushdownsystem, it is built incrementally—node by node, edge by edge. Thenaıve fixed point algorithm presented earlier, if implemented liter-ally, would (in the worst case) have to re-examine the entire DSG toadd each edge. To avoid such re-examination, our implementationadds ✏-summary edges to the DSG.

In short, an ✏-summary edge connects two control states if thereexists a path between them with no net stack change—that is,all pushes are cancelled by corresponding pops. With ✏-summaryedges available, any change to the graph can be propagated directlyto where it has an effect, and then any new ✏-summary edges thatpropagation implies are added.

Whereas the correspondence between CESK and an IPDS is rela-tively straightforward, the relationship between a DSG and its orig-inal IPDS is complicated by the fact that the IPDS keeps track ofthe whole stack, whereas the DSG distributes (the same) stack in-formation throughout its internal structure.

A classic reachability-based analysis for a pushdown system re-quires two mutually-dependent pieces of information in order toadd another edge:

1. The topmost frame on a stack for a given control state q. This isessential for return transitions, as this frame should be poppedfrom the stack and the store and the environment of a callershould be updated respectively.

2. Whether a given control state q is reachable or not from the ini-tial state q0 along realizable sequences of stack actions. For ex-ample, a path from q0 to q along edges labeled “push, pop, pop,push” is not realizable: the stack is empty after the first pop, sothe second pop cannot happen—let alone the subsequent push.

These two data are enough for a classic pushdown reachabilitysummarization to proceed one step further. However, the presenceof an abstract garbage collector, and the graduation to an introspec-tive pushdown system, imposes the requirement for a third item ofdata:

3. For a given control state q, what are all possible frames thatcould happen to be on the stack at the moment the IPDS is inthe state q?

It is possible to recompute these frames from scratch in each it-eration using the NFA-extraction technique we described. But, itis easier to maintain per-node summaries, in the same spirit as ✏-summary edges.

A version of the classic pushdown summarization algorithm thatmaintains the first two items is presented in [4], so we will justoutline the key differences here.

The crux of the algorithm is to maintain for each node q0 in theDSG, a set of ✏-predecessors, i.e., nodes q, such that q 7�!�!~g

M q0

and [~g] = ✏. In fact, only two out of three kinds of transitions cancause a change to the set of ✏-predecessors for a particular node q:an addition of an ✏-edge or a pop edge to the DSG.

It is easy to see why the second action might introduce new ✏-pathsand, therefore, new ✏-predecessors. Consider, for example, addingthe ��-edge q⇢�� q0 into the following graph:

q0�+ // q q0

✏ // q1

As soon this edge drops in, there becomes an “implicit” ✏-edgebetween q0 and q1 because the net stack change between them isempty; the resulting graph looks like:

q0�+ //

q

�� // q0✏ // q1

where we have illustrated the implicit ✏-edge as a dashed line.

A little reflection on ✏-predecessors and top frames reveals a mutualdependency between these items during the construction of a DSG.Informally:

• A top frame for a state q can be pushed as a direct predecessor,or as a direct predecessor to an ✏-predecessor.

• When a new ✏-edge q✏�! q0 is added, all ✏-predecessors of q

become also ✏-predecessors of q0. That is, ✏-summary edges aretransitive.

• When a ��-pop-edge q����! q0 is added, new ✏-predecessors of

a state q1 can be obtained by checking if q0 is an ✏-predecessorof q1 and examining all existing ✏-predecessors of q, such that�+ is their possible top frame: this situation is similar to the onedepicted in the example above.

The third component—all possible frames on the stack for a stateq—is straightforward to compute with ✏-predecessors: startingfrom q, trace out only the edges which are labeled ✏ (summaryor otherwise) or �+. The frame for any action �+ in this trace isa possible stack action. Since these sets grow monotonically, it iseasy to cache the results of the trace, and in fact, propagate incre-mental changes to these caches when new ✏-summary or �+ nodesare introduced. Our implementation directly reflects the optimiza-tions discussed above.

8.2 Experimental results

A fair comparison between different families of analyses shouldcompare both precision and speed. We have extended an existing

Page 10: Introspective Pushdown Analysis of Higher-Order Programs

Program Exp Var k k-CFA k-PDCFA k-CFA + GC k-PDCFA + GC

mj09 19 8 0 83 107 4 38 38 4 36 39 4 33 32 41 454 812 1 44 48 1 34 35 1 32 31 1

eta 21 13 0 63 74 4 34 34 6 28 27 8 28 27 81 33 33 8 32 31 8 28 27 8 28 27 8

kcfa2 20 10 0 194 236 3 36 35 4 35 43 4 35 34 41 970 1935 1 87 144 2 35 34 2 35 34 2

kcfa3 25 13 0 272 327 4 58 63 5 53 52 5 53 52 51 > 7119 > 14201 1 1761 4046 2 53 52 2 53 52 2

blur 40 20 0 > 1419 > 2435 3 280 414 3 274 298 9 164 182 91 261 340 9 177 189 9 169 189 9 167 182 9

loop2 41 14 0 228 252 4 113 122 4 86 93 4 70 74 41 > 10867 > 16040 3 411 525 3 151 163 3 145 156 3

sat 63 31 0 > 5362 > 7610 6 775 979 6 1190 1567 6 321 384 61 > 8395 > 12391 6 7979 10299 6 982 1330 7 107 106 13

Figure 6. Benchmark results. The first three columns provide the name of a benchmark, the number of expressions and variables in theprogram in the ANF, respectively. For each of eight combinations of pushdown analysis, k 2 {0, 1} and garbage collection on or off, the firsttwo columns in a group show the number of control states and transitions/DSG edges computed during the analysis (for both less is better).The third column presents the amount of singleton variables, i.e, how many variables have a single lambda flow to them (more is better).Inequalities for some results denote the case when the analysis did not finish within 30 minutes. For such cases we can only report an upperbound of singleton variables as this number can only decrease.

implementation of k-CFA to optionally enable pushdown analysis,abstract garbage collection or both. Our implementation source andbenchmarks are available:

http://github.com/ilyasergey/reachability

As expected, the fused analysis does at least as well as the bestof either analysis alone in terms of singleton flow sets (a goodmetric for program optimizability) and better than both in somecases. Also worthy of note is the dramatic reduction in the sizeof the abstract transition graph for the fused analysis—even ontop of the already large reductions achieved by abstract gabargecollection and pushdown flow analysis individually. The size of theabstract transition graph is a good heuristic measure of the temporalreasoning ability of the analysis, e.g., its ability to support model-checking of safety and liveness properties [12].

In order to exercise both well-known and newly-presented in-stances of CESK-based CFAs, we took a series of small bench-marks exhibiting archetypal control-flow patterns (see Figure 6).Most benchmarks are taken from the CFA literature: mj09 is a run-ning example from the work of Midtgaard and Jensen designed toexhibit a non-trivial return-flow behavior, eta and blur test com-mon functional idioms, mixing closures and eta-expansion, kcfa2and kcfa3 are two worst-case examples extracted from Van Hornand Mairson’s proof of k-CFA complexity [21], loop2 is an ex-ample from the Might’s dissertation that was used to demonstratethe impact of abstract GC [11, Section 13.3], sat is a brute-forceSAT-solver with backtracking.

8.2.1 Comparing precision

In terms of precision, the fusion of pushdown analysis and abstractgarbage collection substantially cuts abstract transition graph sizesover one technique alone.

We also measure singleton flow sets as a heuristic metric for preci-sion. Singleton flow sets are a necessary precursor to optimizationssuch as flow-driven inlining, type-check elimination and constantpropagation. Here again, the fused analysis prevails as the best-of-or better-than-both-worlds.

Program 0-CFA 0-PDCFA 1-CFA 1-PDCFAmj09 1

00 ✏ ✏ 1

004

00 ✏ ✏ ✏eta ✏ ✏ ✏ ✏ 1

00 ✏ ✏ ✏kcfa2 1

00 ✏ ✏ 1

0024

00 ✏ 1

00 ✏kcfa3 2

00 ✏ ✏ 1

00 1 1

0058

002

00

blur 1 7

002

050

004

030

0011

0055

00

loop2 36

001

0029

0016

00 1 5

0013

02

0

sat 1 45

006

019

0 1 3

012

037

00

Figure 7. We ran our benchmark suite on a 2 Core 2.66 GHz OS Xmachine with 4 Gb RAM. For each of the four analyses the leftcolumn denotes the values obtained with no abstract collection,and the right one—with GC on. The results of the analyses arepresented in minutes (0) or seconds (00), where ✏ means a valueless than 1 second and 1 stands for an analysis, which has beeninterrupted due to the an execution time greater than 30 minutes.

Running on the benchmarks, we have revalidated hypotheses aboutthe improvements to precision granted by both pushdown analy-sis [22] and abstract garbage collection [11]. The table in Figure 6contains our detailed results on the precision of the analysis.

8.2.2 Comparing speed

In the original work on CFA2, Vardoulakis and Shivers presentexperimental results with a remark that the running time of theanalysis is proportional to the size of the reachable states [22,Section 6]. There is a similar correlation in the fused analysis, butit is not as strong or as absolute. From examination of the results,this appears to be because small graphs can have large stores insideeach state, which increases the cost of garbage collection (and thustransition) on a per-state basis, and there is some additional per-transition overhead involved in maintaining the caches inside theDyck state graph. Table 7 collects absolute execution times forcomparison.

It follows from the results that pure machine-style k-CFA is alwayssignificantly worse in terms of execution time than either withGC or push-down system. The histogram on Figure 8 presents

Page 11: Introspective Pushdown Analysis of Higher-Order Programs

Figure 8. Analysis times relative to worst (= 1) in class; smaller is better. On the left is the monovariant 0CFA class of analyses, on the rightis the polyvariant 1CFA class of analyses. (Non-GC k-CFA omitted.)

normalized relative times of analyses’ executions. About half thetime, the fused analysis is faster than one of pushdown analysisor abstract garbage collection. And about a tenth of the time, it isfaster than both.5 When the fused analysis is slower than both, itis generally not much worse than twice as slow as the next slowestanalysis.

Given the already substantial reductions in analysis times providedby collection and pushdown anlysis, the amortized penalty is asmall and acceptable price to pay for improvements to precision.

9. Related work

Garbage-collecting pushdown control-flow analysis draws on workin higher-order control-flow analysis [19], abstract machines [5]and abstract interpretation [3].

Context-free analysis of higher-order programs The motivatingwork for our own is Vardoulakis and Shivers very recent discoveryof CFA2 [22]. CFA2 is a table-driven summarization algorithm thatexploits the balanced nature of calls and returns to improve return-flow precision in a control-flow analysis. Though CFA2 exploitscontext-free languages, context-free languages are not explicit in itsformulation in the same way that pushdown systems are explicit inour presentation of pushdown flow analysis. With respect to CFA2,our pushdown flow analysis is also polyvariant/context-sensitive(whereas CFA2 is monovariant/context-insensitive), and it coversdirect-style.

On the other hand, CFA2 distinguishes stack-allocated and store-allocated variable bindings, whereas our formulation of pushdowncontrol-flow analysis does not: it allocates all bindings in the store.If CFA2 determines a binding can be allocated on the stack, thatbinding will enjoy added precision during the analysis and is notsubject to merging like store-allocated bindings. While we couldincorporate such a feature in our formulation, it is not necessaryfor achieving “pushdownness,” and in fact, it could be added toclassical finite-state CFAs as well.

5 The SAT-solving bechmark showed a dramatic improvement with the ad-dition of context-sensitivity. Evaluation of the results showed that context-sensitivity provided enough fuel to eliminate most of the non-determinismfrom the analysis.

Calculation approach to abstract interpretation Midtgaard andJensen [10] systematically calculate 0CFA using the Cousot-Cousot-style calculational approach to abstract interpretation [2]applied to an ANF �-calculus. Like the present work, Midtgaardand Jensen start with the CESK machine of Flanagan et al. [6] andemploy a reachable-states model.

The analysis is then constructed by composing well-known Galoisconnections to reveal a 0CFA incorporating reachability. The ab-stract semantics approximate the control stack component of themachine by its top element. The authors remark monomorphismmaterializes in two mappings: “one mapping all bindings to thesame variable,” the other “merging all calling contexts of the samefunction.” Essentially, the pushdown 0CFA of Section 4 corre-sponds to Midtgaard and Jensen’s analysis when the latter map-ping is omitted and the stack component of the machine is not ab-stracted.

CFL- and pushdown-reachability techniques This work alsodraws on CFL- and pushdown-reachability analysis [1, 8, 17, 18].For instance, ✏-closure graphs, or equivalent variants thereof, ap-pear in many context-free-language and pushdown reachabilityalgorithms. For our analysis, we implicitly invoked these methodsas subroutines. When we found these algorithms lacking (as withtheir enumeration of control states), we developed Dyck state graphconstruction.

CFL-reachability techniques have also been used to compute clas-sical finite-state abstraction CFAs [9] and type-based polymorphiccontrol-flow analysis [16]. These analyses should not be confusedwith pushdown control-flow analysis, which is computing a fun-damentally more precise kind of CFA. Moreover, Rehof and Fah-ndrich’s method is cubic in the size of the typed program, but thetypes may be exponential in the size of the program. Finally, ourtechnique is not restricted to typed programs.

Model-checking higher-order recursion schemes There is ter-minology overlap with work by Kobayashi [7] on model-checkinghigher-order programs with higher-order recursion schemes, whichare a generalization of context-free grammars in which produc-tions can take higher-order arguments, so that an order-0 schemeis a context-free grammar. Kobyashi exploits a result by Ong [15]which shows that model-checking these recursion schemes is de-cidable (but ELEMENTARY-complete) by transforming higher-order programs into higher-order recursion schemes.

Page 12: Introspective Pushdown Analysis of Higher-Order Programs

Given the generality of model-checking, Kobayashi’s techniquemay be considered an alternate paradigm for the analysis of higher-order programs. For the case of order-0, both Kobayashi’s tech-nique and our own involve context-free languages, though ours isfor control-flow analysis and his is for model-checking with respectto a temporal logic. After these surface similarities, the techniquesdiverge. In particular, higher-order recursions schemes are limitedto model-checking programs in the simply-typed lambda-calculuswith recursion.

10. Conclusion

Our motivation was to further probe the limits of decidability forpushdown flow analysis of higher-order programs by enriching itwith abstract garbage collection. We found that abstract garbagecollection broke the pushdown model, but not irreparably so. Bycasting abstract garbage collection in terms of an introspectivepushdown system and synthesizing a new control-state reachabilityalgorithm, we have demonstrated the decidability of fusing twopowerful analytic techniques.

As a byproduct of our formulation, it was also easy to demon-strate how polyvariant/context-sensitive flow analyses generalizeto a pushdown formulation, and we lifted the need to transform tocontinuation-passing style in order to perform pushdown analysis.

Our empirical evaluation is highly encouraging: it shows that thefused analysis provides further large reductions in the size of theabstract transition graph—a key metric for interprocedural control-flow precision. And, in terms of singleton flow sets—a heuristicmetric for optimizability—the fused analysis proves to be a “better-than-both-worlds” combination.

Thus, we provide a sound, precise and polyvariant introspectivepushdown analysis for higher-order programs.

Acknowledgments

We thank our anonymous reviewers for their detailed commentson the submitted paper. This material is based on research spon-sored by DARPA under the programs Automated Program Anal-ysis for Cybersecurity (FA8750-12-2-0106) and Clean-Slate Re-silient Adaptive Hosts (CRASH). The U.S. Government is autho-rized to reproduce and distribute reprints for Governmental pur-poses notwithstanding any copyright notation thereon.

References[1] BOUAJJANI, A., ESPARZA, J., AND MALER, O. Reachability

analysis of pushdown automata: Application to Model-Checking. InCONCUR ’97: Proceedings of the 8th International Conference onConcurrency Theory (1997), Springer-Verlag, pp. 135–150.

[2] COUSOT, P. The calculational design of a generic abstract interpreter.In Calculational System Design, M. Broy and R. Steinbruggen, Eds.1999.

[3] COUSOT, P., AND COUSOT, R. Abstract interpretation: A unifiedlattice model for static analysis of programs by construction orapproximation of fixpoints. In Conference Record of the FourthACM Symposium on Principles of Programming Languages (1977),ACM Press, pp. 238–252.

[4] EARL, C., MIGHT, M., AND VAN HORN, D. Pushdown control-flow analysis of higher-order programs. In Proceedings of the 2010Workshop on Scheme and Functional Programming (Aug. 2010).

[5] FELLEISEN, M., AND FRIEDMAN, D. P. A calculus for assignmentsin higher-order languages. In POPL ’87: Proceedings of the 14thACM SIGACT-SIGPLAN Symposium on Principles of ProgrammingLanguages (1987), ACM, pp. 314+.

[6] FLANAGAN, C., SABRY, A., DUBA, B. F., AND FELLEISEN, M. Theessence of compiling with continuations. In PLDI ’93: Proceedingsof the ACM SIGPLAN 1993 Conference on Programming LanguageDesign and Implementation (June 1993), ACM, pp. 237–247.

[7] KOBAYASHI, N. Types and higher-order recursion schemes forverification of higher-order programs. In POPL ’09: Proceedings ofthe 36th Annual ACM SIGPLAN-SIGACT Symposium on Principlesof Programming Languages (2009), POPL ’09, ACM, pp. 416–428.

[8] KODUMAL, J., AND AIKEN, A. The set constraint/CFL reachabilityconnection in practice. SIGPLAN Not. 39 (June 2004), 207–218.

[9] MELSKI, D., AND REPS, T. W. Interconvertibility of a class ofset constraints and context-free-language reachability. TheoreticalComputer Science 248, 1-2 (Oct. 2000), 29–98.

[10] MIDTGAARD, J., AND JENSEN, T. P. Control-flow analysis offunction calls and returns by abstract interpretation. In ICFP ’09:Proceedings of the 14th ACM SIGPLAN International Conference onFunctional Programming (2009), pp. 287–298.

[11] MIGHT, M. Environment Analysis of Higher-Order Languages. PhDthesis, Georgia Institute of Technology, June 2007.

[12] MIGHT, M., CHAMBERS, B., AND SHIVERS, O. Model checkingvia Gamma-CFA. In Verification, Model Checking, and AbstractInterpretation (Jan. 2007), pp. 59–73.

[13] MIGHT, M., AND SHIVERS, O. Environment analysis via Delta-CFA. In POPL ’06: Conference Record of the 33rd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages(2006), ACM, pp. 127–140.

[14] MIGHT, M., AND SHIVERS, O. Improving flow analyses via Gamma-CFA: Abstract garbage collection and counting. In ICFP ’06:Proceedings of the 11th ACM SIGPLAN International Conferenceon Functional Programming (2006), ACM, pp. 13–25.

[15] ONG, C. H. L. On Model-Checking trees generated by Higher-Orderrecursion schemes. In 21st Annual IEEE Symposium on Logic inComputer Science (LICS’06) (2006), pp. 81–90.

[16] REHOF, J., AND FAHNDRICH, M. Type-based flow analysis:From polymorphic subtyping to CFL-reachability. In POPL ’01:Proceedings of the 28th ACM SIGPLAN-SIGACT Symposium onPrinciples of Programming Languages (2001), ACM, pp. 54–66.

[17] REPS, T. Program analysis via graph reachability. Information andSoftware Technology 40, 11-12 (Dec. 1998), 701–726.

[18] REPS, T., SCHWOON, S., JHA, S., AND MELSKI, D. Weightedpushdown systems and their application to interprocedural dataflowanalysis. Science of Computer Programming 58, 1-2 (2005), 206–263.

[19] SHIVERS, O. G. Control-Flow Analysis of Higher-Order Languages.PhD thesis, Carnegie Mellon University, 1991.

[20] SIPSER, M. Introduction to the Theory of Computation, 2 ed. CourseTechnology, Feb. 2005.

[21] VAN HORN, D., AND MAIRSON, H. G. Deciding kCFA iscomplete for EXPTIME. In ICFP ’08: Proceeding of the 13th ACMSIGPLAN International Conference on Functional Programming(2008), pp. 275–282.

[22] VARDOULAKIS, D., AND SHIVERS, O. Cfa2: a Context-FreeApproach to Control-Flow Analysis. In European Symposium onProgramming (ESOP) (2010), vol. 6012 of LNCS, pp. 570–589.

[23] WRIGHT, A. K., AND JAGANNATHAN, S. Polymorphic splitting:An effective polyvariant flow analysis. ACM Transactions onProgramming Languages and Systems 20, 1 (Jan. 1998), 166–207.