Generalized Escape Analysis and Lightweight Continuations

Generalized Escape Analysis and Lightweight Continuations

Generalized Escape Analysis and Lightweight Continuations Abstract Might and Shivers have published two distinct analyses for rea- ∆CFA and ΓCFA are two analysis techniques for higher-order soning about programs written in higher-order languages that pro- functional languages (Might and Shivers 2006b,a). The former uses vide first-class continuations, ∆CFA and ΓCFA (Might and Shivers an enrichment of Harrison’s procedure strings (Harrison 1989) to 2006a,b). ∆CFA is an abstract interpretation based on a variation reason about control-, environment- and data-flow in a program of procedure strings as developed by Sharir and Pnueli (Sharir and represented in CPS form; the latter tracks the degree of approxi- Pnueli 1981), and, most proximately, Harrison (Harrison 1989). mation inflicted by a flow analysis on environment structure, per- Might and Shivers have applied ∆CFA to problems that require mitting the analysis to exploit extra precision implicit in the flow reasoning about the environment structure relating two code points lattice, which improves not only the precision of the analysis, but in a program. ΓCFA is a general tool for “sharpening” the precision often its run-time as well. of an abstract interpretation by tracking the amount of abstraction In this paper, we integrate these two mechanisms, showing how the analysis has introduced for the specific abstract interpretation ΓCFA’s abstract counting and collection yields extra precision in being performed. This permits the analysis to opportunistically ex- ∆CFA’s frame-string model, exploiting the group-theoretic struc- ploit cases where the abstraction has introduced no true approxi- ture of frame strings. mation. We apply the improved ∆CFA to escape analysis (discovering Our message in this paper is that these two techniques are syn- when procedures can have their environment records allocated on ergistic: the extra precision provided by ΓCFA is exactly what is the stack), and lightweight continuation creation (when continu- needed for us to perform extra “cancellations” in a critical approx- ations created with call/cc can be implemented with a simple imation step of ∆CFA. This specifically improves our ability to stack pointer, eliminating the need to copy the stack out into heap reason about a program’s stack behaviour, and consequently, can storage). While Might and Shivers’s description of ∆CFA applied be applied profitably to code improvements based on escape anal- the analysis to general environment problems in functional lan- ysis. (We should note that while procedure-string abstractions are guages, here we focus on reasoning about stack behaviour, which especially well suited to discovering properties about the run-time is, in fact, the strength of the model, thus returning to the origi- stack, Might and Shivers’ development of ∆CFA did not focus on nal application for which Harrison designed its “procedure-string” this area of analysis.) predecessor. Additionally, the precision improvements are also specifically The paper includes a complete, standalone reformulation of good for situations that arise in reasoning about and fusing net- ∆CFA; a new, factored abstraction for frame-strings; a generaliza- works of coroutines. tion to alternate stack models; a discussion of frame-string-based This work contributes: escape analysis; a review of our implementation and results; and a • A framework for an escape analysis that generalizes to more description of lightweight continuation conversion. exotic stack and control mechanisms, such as coroutines and cooperative multithreading. • A novel abstraction for frame strings that is compatible with 1. Introduction the ΓCFA technology suite—abstract counting and abstract garbage collection (Might and Shivers 2006b). In particular, An entire class of analyses is devoted to reasoning about the life- abstract counting allows this new abstraction to recover enough times of dynamically allocated objects. If, for example, an analysis of the group-theoretic properties of frame strings in the abstract can derive that some object is never accessed after its allocating to handle coroutines. procedure returns, then this object can be allocated on the run-time • stack, rather than in the garbage-collected heap. In higher-order An optimization, lightweight continuation conversion, designed functional languages, such as Scheme, SML and Haskell, these ob- to reduce continuation objects from entire stack copies to just a jects can include procedures and continuations created with primi- single pointer. tives such as Scheme’s call/cc operator. Higher-order languages • A method for verifying the safety of constrained stack-plus- (by which we mean object-oriented languages as well as functional control-flow manipulation operators such as C’s setjmp and ones) complicate matters, as program execution can proceed “into” longjmp. these dynamically (and possibly stack-) allocated objects. When we add general continuations to the set of possibilities, things be- come even more complex, as continuations themselves represent 2. Partitioned CPS entire stack contexts. An object can be allocated, then returned past In the interests of a self-contained presentation, we now recap the its creator’s stack frame and later invoked, yet still be invoked in basic development of ∆CFA before introducing our ΓCFA-based a context “below” its creator’s frame, if its creation context hap- improvements. ∆CFA (Might and Shivers 2006a), operates over a pened to be captured by an escaping continuation that is later used syntactically partitioned continuation-passing style (CPS) (Steele to restore this context. Jr. 1978) input language. Partitioned CPS is intended for use as One reason continuations are an important construct to anal- an intermediate form generated from programs written in a direct- yse is that they can be used to implement coroutines; reasoning style λ-calculus language, with user-level access to full, first-class about continuations enables us to implement these coroutines in continuations, such as Scheme or SML/NJ. a lightweight, fusible manner. Fusible coroutines are a linguis- By partitioned, we mean that all the forms (variables, call ar- tic facility that permits the construction of modular but high- guments, calls and λ expressions) are statically marked as belong- performance stream-processing applications (Shivers and Might ing to either the user world, or the continuation world. The term 2006). user world emphasizes the fact that continuation forms cannot be (rcs 1.23 (2007 7 14)) (define fact pr ∈ PR ::= (λ (halt) call) (λ (n k) v ∈ VAR = UVAR + CVAR (%if-zero n u ∈ UVAR = a set of identifiers (λ () [k 1]) k ∈ CVAR = a set of identifiers (λ () (- n 1 (λ (m) lam ∈ LAM = ULAM + CLAM (fact m (λ (a) (* a n k))))))))) ulam ∈ ULAM ::= (λℓ (u k) call) clam ∈ CLAM ::= (λγ (u) call) Figure 2. Recursive factorial written in CPS. Continuation λ terms are marked with an underline; continuation calls are marked with f , x ∈ EXP = UEXP + CEXP square brackets. The two-way conditional is encoded by the primi- h, e ∈ UEXP = UVAR + ULAM tive procedure %if-zero, which takes an integer and two continu- q ∈ CEXP = CVAR + CLAM ations. call ∈ CALL = UCALL + CCALL ucall ∈ UCALL ::= (h eq)ℓ ccall ∈ CCALL ::= (q e) γ the definition of square contains within it a multiplication step). ψ, κ ∈ LAB = ULAB + CLAB Notice how the call/return entries properly nest like brackets. ℓ ∈ ULAB = a set of labels We can view this trace, or procedure string, as a sequence γ ∈ CLAB = a set of labels of control (call/return) operations, but we can also view it as a sequence of stack (push/pop) operations. However, in functional Figure 1. Partitioned CPS languages, this direct correspondence between control and stack operations breaks down somewhat. For example, we write loops in functional languages with tail-recursive function calls. A functional programmer would think of a fifty-iteration loop as consisting expressed directly by the programmer (the user) in the original, of fifty calls followed by a single return. Similarly, exceptions, direct-style source. In the translation from direct-style code to CPS, coroutines and general continuation invocation all depart from the each λ expression from the source maps to a “user” λ expression, simple model, where calls and returns nest in a simple way. while return points or evaluation context in the direct-style form are However, no matter what the call/return behaviour is, it is still mapped to “continuation” λ expressions. true that the associated stack operations nest properly. That is, if we The point of partitioning is two-fold: push frame a, then push frame b, the two frames will necessarily be • It permits us to exploit a cheaply obtained partition amongst the popped in the order “b, then a.” Might and Shivers pointed out that abstract-semantic elements of our analysis; we get a more precise model of program behaviour in the presence • of these control constructs if we take models based on procedure yet we can otherwise operate in a general CPS setting, where strings and change to abstractions whose nesting and cancellation we can express and reason about all control and environment properties are driven by analogues to stack behaviour (Might and structure in the program via the uniform, universal mechanism Shivers 2006a). of a CPS procedure call. This takes us from the classic, “FORTRAN-like” view of proce- Looking ahead, this partitioning preserves enough information to dure call to the view articulated in Steele’s Rabbit thesis (Steele Jr. allow us to recover stack operations, which is the focus of our 1978). Steele’s protocol for function call is the basic mechanism analysis. that manages a stack properly in the functional-language setting Figure 1 gives the partitioned CPS grammar. Every syntactic we’ve described. When we shift to a partitioned CPS representa- category—VAR, LAM , EXP and CALL—is composed of a user- tion, this protocol is directly tied to the syntax. world set and a continuation-world set. We mark user-world λ ex- pressions and calls with labels ℓ ∈ ULAB, while continuation- world items are marked with distinct labels γ ∈ CLAB.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    11 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us