Referencing and .Retention in Block-Structured Coroutines - CiteSeerX

5 downloads 0 Views 2MB Size Report
Given (AR6) and (AR7), we can prove the following useful fact. THEOREM 6. If policy (b) (or (a)) is in effect, then (AR4)-(AR5) may be combined as follows:.
Referencing and .Retention in Block-Structured Coroutines GARY LINDSTROM The University of Utah and MARY LOU SOFFA The University of Pittsburgh

The combination of coroutines with recursive procedures is characteristic of many modern higher level languages offering advanced control structures (e.g., SIMULA-67, SL5, or INTERLISP). We say a language has block-structured coroutines (BSCRs) when static nesting considerations govern the usage of this control combination. Starting with the BSCR control description work of Wang and Dahl, this paper pursues further the implications of static program structure on BSCR programs in a particular compilation-oriented setting. Disciplines on BSCR reference assignment and individual control actions are defined, offering enhanced implementability and program comprehensibility. Of particular interest is a scope-based discipline on "detach" operations, which avoids the formation of idle chain subheads, an implementationally undesirable condition. The retention requirements of BSCRs are analyzed under a range of possible remote accessibility conditions, and two deletion strategies are then defined, keyed to these requirements. The first uses a special form of scopesensitive reference counting, and the second does mark-sweep garbage collection, again exploiting static program structure. Space and time estimates for both methods are given, along with avenues for continuing research. Key Words and Phrases: coroutines, static nesting, deletion strategies, reference counting, garbage collection, remote accessing CR Categories: 4.12, 4.22

1. INTRODUCTION 1.1 Importance of Logical Parallelism L o g i c a l p a r a l l e l i s m a s a p r o g r a m m i n g c o n c e p t is g r o w i n g i n i m p o r t a n c e a s h i g h e r level programming languages (HLLs) become more widely adopted. Application areas such as systems programming, real-time control, simulation, and heuristic searching are but a few of the domains better served by HLLs possessing control Permission to copy without fee all or part of this material is granted provided that the copies are not made or distributed for direct commercial advantage, the ACM copyright notice and the title of the publication and its date appear, and notice is given that copying is by permission of the Association for Computing Machinery. To copy otherwise, or to republish, requires a fee and/or specific permission. This work was supported in part by grant MCS-78-03832 from the National Science Foundation to the University of Utah and grant MCS-79-06102 from the National Science Foundation to the University of Pittsburgh. Authors' addresses: G. Lindstrom, Department of Computer Science, The University of Utah, 3160 Merrill Engineering Building, Salt Lake City, U T 84112; M. L. Sofia, Department of Computer Science, University of Pittsburgh, Pittsburgh, PA 15260. © 1981 ACM 0164-0925/81/0700-0263 $00.75 ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981, Pages 263-292.

264

Gary Lindstrom and Mary Lou Sofia

structures that go beyond a purely stack-based hierarchy. The term coroutine, originally introduced by Conway [6] to characterize the coexistent phase organization often found in compilers, is commonly used to describe such logically parallel program units. When coupled with recursion in HLLs, coroutines become an extremely flexible tool for algorithm specification. In such a combination recursion contributes dynamic storage allocation and hierarchical environment sharing, while coroutines contribute control versatility within those environments. From these two bases a remarkably wide range of control effects can be achieved, including backtracking [10], pattern-directed invocation [16], and deferred evaluation [9], among many others. While this versatility is clearly an asset, it is also a liability in that poorly structured control regimes can be encouraged. Thus, while languages of this variety possessing purely dynamic control semantics have obvious experimental merit (e.g., SL5 [11]), other languages incorporating coroutines into more compilation-oriented languages with static block structure are likely to have greater ultimate impact. We term this class of languages block-structured coroutine (BSCR) languages. Within this domain, SIMULA-67 [8] offers the most advanced design generally available today. 1.2 Disciplines on BSCR Usage

SIMULA-67 illustrates well the benefits to be obtained by placing disciplines on BSCR usage. These benefits include (1) implementation economies (such as compile-time reference security); (2) useful semantic concepts offering structure (such as "operating chain," "attachment" versus "detachment") in an otherwise amorphous control domain; and (3) convenient control "packages" of higher level notions (such as the time-based pseudoparallel control in the system class SIMULATION). A formal description of SIMULA-67's control behavior (in part) has been offered by Wang and Dahl [23]. However, this early work focused on points (2) and (3) above and ignored such issues as reference variable scoping rules and the enforcement of control event disciplines. While we do not here seek to give a full description of SIMULA-67's control structures, nor even a proper subset thereof, • we do address these issues and others, both conceptual and implementational, in a BSCR setting chosen especially to exploit program static structure. 1.3 Overview

We begin by reviewing Wang and Dahl's axiomatic method for describing BSCRs in Section 2 and make some clarifying observations on possible BSCR control states. The method is extended in Section 3 to include coroutine instance reference variables, constrained to obey certain static scoping rules. The implementation of our selected control event and reference scoping disciplines is treated in Section 4. As a prelude to the consideration of BSCR deletion strategies, we present postulates in Section 5 that define the retention requirements of our class of BSCRs. In Section 6 an incremental deletion strategy ~', based on a new A C M Transactions on P r o g r a m m i n g Languages and Systems, Vol. 3, No. 3, J u l y 1981.

Referencing and Retention in Block-Structured Coroutines

265

scope-based approach to reference counting, is described. Since ~ ' is not complete (in that it overlooks certain cyclic structures), a companion method ~", based on a form of scope-based mark-sweeping (garbage collection), is presented in Section 7. Section 8 provides a summary and evaluation of our results. 1.4 Visibility and Scoping

Our treatment here is based on the following range of identifier visibility and program nesting rules. (1) For simplicity, we assume that coroutine definitions are the only program units involving scoping (since blocks and procedures are logically subsumed). Moreover, we assume that the program consists of a single textually nested set of such definitions (hence separate compilation is ignored). (2) All variables must be explicitly declared local to some coroutine definition. Creation of a coroutine instance causes the creation of an instance of each locally declared variable, which is d i r e c t l y a c c e s s i b l e via its associated identifier throughout the static scope of that coroutine instance (barring redeclaration of that identifier). (3) A coroutine reference variable may be assigned the name of any coroutine instance in whose static scope it lies, or that of an immediate static descendant of such an instance. (4) We consider three distinct policies concerning the r e m o t e a c c e s s of a variable through a reference variable holding the name of the coroutine instance local to which it was created: Policy (a): no such remote access is permitted; Policy (b): remote access is permitted only to nonreference variables; and Policy (c): remote access is permitted to all variables. 1.5 Previous Work

There has been a wide variety of approaches to the formulation of coroutines; indeed, the title of McIlroy's unpublished but widely circulated memo accurately reflects the situation to this day [17]. Of the few approaches dealing explicitly with scoping issues, the work of Krieg [14] and Vanek [22] is most notable. T he latter is of particular interest as a contrast to this work, since in Vanek's approach BSCRs are defined without appeal to programmer-manipulatable reference variables. Approaches to coroutine implementation based on reference counting may be found in [2, 12]; coroutine implementation through garbage collection is studied in [1, 3]. A mixed strategy involving both reference counting and garbage collection may be seen in [4]. Verificational aspects of coroutine programming have been approached in [5, 7]. 2. PRELIMINARIES 2.1 Wang and Dahl's Approach to Control Description

Wang and Dahl approach the description of BSCRs by considering an abstract representation of run-time control states. This representation consists of the set ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

266

Gary Lindstrom and Mary Lou Sofia

of dynamic procedure I instances (activations) in existence at any m o m e n t and key relationships t h a t exist a m o n g those instances. T h e relationships of interest are the d y n a m i c (i.e., control) and static (i.e., textual) connections a m o n g the instances. 2.1.1 P r i m i t i v e Symbols. Following the notation of W a n g and Dahl, we make use of the following primitive symbols: £f the set of all procedure instances in existence at any m o m e n t ; x.SC, for x E 5z the return link of x, a pair of the form

[ip: r e t u r n code pointer, ep: calling instance]; D P

T --~

OC

a function 5P--->5z denoting dynamic enclosure (called --> caller), with D(x) - x.SC.ep; the processor, in 5z by extension. B y special convention, P.SC.ep - D ( P ) - the currently operating instance, and P.SC.ip - the p r o g r a m counter of P; a function ~ - {P} --> $z denoting static enclosure ( d e c l a r e d - - ) declarer); a binary relation on ~ defined to be x --~ y --- x ~ P A D(x) = y; its transitive closure is x ---)+ y - x --> y V (x ~ P A D(x) ---)+ y), and its transitive and reflexive closure is x -o* y =- x = y V (x ~ P A D(x) ---)* y); a binary relation on ~ defined to be x ~ y --- x ~ P A T(x) = y; its transitive closure is x ~ + y =- x ~ y V (x ~ P A T(x) ~ + y), and its transitive and reflexive closure is x ~ * y = x = y V (x ~ P A T(x) ~ * y). We define v(y) = {x I x ~ * y}; and the set of instances dynamically linked from D(P), t h a t is, ( Y l D ( P ) -o* y}, is t e r m e d the operating c h a i n (OC). An instance x is said to be active iff x E OC. If x is active and x --~+ y, we say y is "to the right of" x on the OC.

2.1.2 Control Events. Using this notation, we can characterize a class of possible control events. T h e s e comprise instance creation (procedure invocation), instance termination, and the coroutine control exchange actions s w a p ( x ) and r o t a t e ( x , y). Initially, D ( P ) = P. (1) invocation: Assume D ( P ) = y and y invokes a procedure x declared local to an instance z. More precisely, x refers to a p r o c e d u r e closure consisting of a code e n t r y point code(x), and a static e n v i r o n m e n t env(x), equal to z, providing a data context for accesses of nonlocal variables from within instances of x. T h e n the result of an invocation of x is the creation of a new instance x of x, adjoined to ~, with T(x) := z, x.SC := D ( P ) . S C (thereby setting D(x) = y), and P.SC := [code(x), x]. See Figure 1. l Blocks in the ALGOL-60 sense are considered here to be s u b s u m e d by the more general notion of procedures. Moreover, since recursion can readily be simulated by LIFO coroutine control, we assume every procedure instance is created as a coroutine. ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Referencing and Retention in Block-Structured Coroutines

Fig. 1.

267

Invocation. D y n a m i c enclosure is indicated by single-stroke arrows a n d textual enclosure by double-stroke arrows.

(a)

(b) Fig. 2.

s w a p ( x ) . T h e transition from s t a t e (a) to s t a t e (b) or vice versa is accomplished by t h e s a m e action. T links are n o t shown.

(2) termination: A s s u m e D ( P ) = x ~ P. T h e t e r m i n a t i o n of x causes P . S C to be set to x.SC and x to be deleted f r o m ~. (3) s w a p ( x ) : T h i s event causes the SC variables of x and P to h a v e their values interchanged, t h a t is, x.SC

P.SC

If x ~ OC, the effect of s w a p ( x ) is a r e t u r n of control to its caller without t e r m i n a t i o n of x (i.e., x "detaches"). x.SC saves the reactivation p o i n t of x. If x ~ OC, the effect of s w a p ( x ) is the e s t a b l i s h m e n t of D ( P ) as the current caller of x and the r e s u m p t i o n of x at its reactivation point (i.e., x is "called"). See Figure 2. (4) r o t a t e ( x , y): T h i s e v e n t causes the SC variables of x, y, and P to h a v e ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

268

Gary Lindstrom and Mary Lou Sofia

14--t x 14-4.1

(Fq-4- -I

Fig. 3.

rotate(x,y).

their values permuted as indicated below: P.SC %

x.SC

y.SC

Th e effect of r o t a t e ( x , y) is equivalent to swap(x) followed immediately by s w a p ( y ) in an indivisible action. See Figure 3. 2.2 Selected Previous Results

2.2.1 L a w a n d O r d e r . In the interest of semantic coherence and enhanced implementability, Wang and Dahl define four "law-and-order" invariants that circumscribe the range of desirable run-time control states. These are (LO1) P ~ 5z; the processor is never deleted; (L02) D is 1-1; all instances are linked by D into one or more cycles; (L03) for all x ~ P: T ( x ) E ~ ; instance deletion observes static nesting order; and (L04) for all x # P: D ( x ) ~ * T(x), a subtle condition relating D and T link nesting. 2.2.2 C o n t r o l E v e n t C o n d i t i o n s . Certain conditions are imposed on control events in order to provide a run-time discipline that will ensure the law-and-order objectives listed above. Assume D ( P ) = w. T h e n these conditions are (1) c a n i n v o k e (CI): whenever the language permits w to invoke a procedure x, with e n v ( x ) = z, we may be sure that w 7 " z; we denote this by w CI x D w ~ * e n v ( x ) ; (2) c a n s w a p ( C S ) : wCSx~wT* T(x);and (3) c a n r o t a t e (CR): w CR (x, y) D w ~ * T ( x ) ~ * T ( y ) . Wang and Dahl prove that these control event conditions are sufficient to preserve (LO1)-(LO4). T he following fact, which will prove useful to us subseACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Referencing and Retention in Block-Structured Coroutines

269

quently, is also established: (LO5) For all w, x: w E OC A w 7 " x D w --** x. T h i s condition states t h a t all T links on the OC are local to the OC and point to the right. 2.2.3 T h e D e l e t i o n nation includes the extend this deletion deletion of instances

S t r a t e g y ~ . As m e n t i o n e d in Section 2.1.2, instance termiaction of deleting t h a t instance f r o m ~. W a n g and D a h l policy to a m o r e c o m p r e h e n s i v e policy ~ t h a t provides for located off the OC:

~: A s s u m e D ( P ) = x ~ y, x ~ P . As the (only) result of the t e r m i n a t i o n of x, P . S C := x.SC (thereby setting D ( P ) = y), and r(x) is deleted f r o m Y. is t h e n p r o v e d to be "safe," in the sense t h a t (LO1)-(LO4) are preserved. One corollary (via (LO2)) is t h a t ~ always deletes entire D cycles. 2.3 T Link Relationships Among Chains

L a w - a n d - o r d e r conditions (LO1)-(LO5) imply a certain structural regularity on T l i n k relationships a m o n g chains. We s u m m a r i z e this s t r u c t u r e for f u r t h e r reader orientation and to aid in later sections. First, a few additional definitions: chain(x), x ~ ~ denotes {y E SP I x --~* y V Y --~* x}; hence chain(P) = OC; denotes the set of i d l e c h a i n s , defined to be {chain(x) Ix E SP/X chain(x) ~ OC}; c# denotes the set of all chains, t h a t is, ~ U (OC} ; h(L), L E aLP denotes the h e a d instance of L, t h a t is, the object of the s w a p (or r o t a t e ) t h a t created L; 5¢~ denotes the set of all h e a d instances, t h a t is, (h(L) I L ~ ~ ) ; and we extend (without confusion) the relation ~ on 5z to a p p l y as well to ~. L e t L, M be in ~. T h e n L ~ M iff L # M and there exist x (5 L, y E M such t h a t x ~ y. Similarly, we a s s u m e ~ + and ~ * to be extended to ~ as well. We now show t h a t ~ imposes a tree structure on ~ as it does on ~. THEOREM 1. T l i n k s o n O C d o n o t cross. M o r e f o r m a l l y , f o r a l l x, y E O C : x ~*

y ~*

T(x) ~*

T(y) D x = y V Y = T(x) V T(x) = T(y).

PROOF. Suppose not. T h e n t h e r e m u s t exist instances x and y E OC such t h a t x ---)÷ y ---)÷ T ( x ) ---~+ T ( y ) ; call this p r o p e r t y TCross(x, y). Select x and y such t h a t

for no z: x --->+ z ---)+ y, TCross(x, z), or TCross(z, y). I f x ~ y, (LO4) is clearly violated. Otherwise, C a s e 1. For all z such t h a t x ---~+ z ----)+ y, z --->+ T ( z ) ---->* y. T h e n D ( x ) =~* y; since y --) + T ( x ) --->÷ T(y), D ( x ) =26* T(x), contradicting (LO4). O

C a s e 2. For some z: x ---) ÷ z ---)+ y, z ---*+ y ---~+ T ( z ) . B u t t h e n i f y --->+ T ( z ) ---)÷ T ( y ) , TCross(z, y); if T ( y ) ---~* T ( z ) , TCross(x, z). Since these are the only two possibilities for T ( z ) b y (LO5), our choice for x and y is contradicted. []

COROLLARY 1.1 w --~* z -->* x E O C / k w 7 "

x D z ~*

x.

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

270

Gary Lindstrom and Mary Lou Sofia

COROLLARY 1.2 L e t L be in ~. T h e n (1) T(h(L)) ~ L a n d (2) for all z ~ L, T(z) E L V T(z) = T(h(L)). PROOF (1) L e t h(L) = x. T h e n , at the creation of L, D ( P ) ~ * T(x), b y CS or CR. Since x E OC at t h a t time, b y (LO5) we h a v e D ( P ) ---** x ---~+ T(x). H e n c e T(x) = T(h(L)) r e m a i n s on the OC w h e n L is formed. (2) S u p p o s e not. T h e n , for s o m e z E L, at the creation of L we h a v e D ( P ) --** z --->+ x --*+ T(z), b y (LO5). Since D ( P ) ~ * T(x), b y Corollary 1.1 necessarily z ~ * T(x). Clearly z ~ T(x), so T(z) 7 " T(x). B y hypothesis, T(z) ~ T(x) = T(h(L)), so T(z) ~ + T(x). T h e n again b y (LO5) we h a v e z --*+ x --*+ T(z) --*+ T(x), contradicting T h e o r e m 1. [] THEOREM 2. T h e relation ~ f o r m s a tree on cd. PROOF. L e t the node set of the tree be ~d, and let an arc be p r e s e n t f r o m L to M iff L ~ M. B y (LO5), the OC h a s no outgoing arcs; this is the root of our tree. B y Corollary 1.2, if L E ~ , t h e n L ~ M iff T(h(L)) E M. H e n c e the o u t d e g r e e of L is one, and we h a v e a tree. [] 3. REFERENCING 3.1

Reference Variables

I n the f o r m a l i s m of Section 2, specific p r o c e d u r e instance n a m i n g m e c h a n i s m s at the source p r o g r a m level ( t h a t is, for use in s w a p ( x ) and r o t a t e ( x , y)) are not considered. N a m e s of p r o c e d u r e instances, however, are d y n a m i c a l l y created and m u s t be m a n i p u l a t e d t h r o u g h the use of reference variables as intermediaries. W e now extend our f o r m a l i s m to deal explicitly with such variables. Our goal here will be to s h a r p e n the control e v e n t definitions a n d conditions of Section 2 in p r e p a r a t i o n for their efficient i m p l e m e n t a t i o n in Sections 4 t h r o u g h 7. 3.1.1 Notation. T h e following additional n o t a t i o n is needed:

t(D g~ e÷ stat(x)

s y m b o l s in lowercase script letters denote reference variables, t h a t is, those p e r m i t t e d to a s s u m e p r o c e d u r e instance n a m e s as values; denotes the instance containing the declaration of e as a local variable; (for " e n v i r o n m e n t descriptors") denotes the set of all reference variables currently existing (i.e., local to a n y existing instance); denotes the instance currently referenced by ~; ~÷ m a y also be the special value nil, which is the initial value of all e E •; for x E 5p denotes the static d e p t h of x, defined to be stat(P) = 0; stat(x) = stat(T(x)) + 1

for

x ~ P;

disp(x, i) for x ~ 5z and 0 < i _ stat(y). [] 4.4 Idle Chain Subheads

As discussed in Section 4.2, Hbit(x) m a y be used to detect immediately if x E J~ but not if x ~ OC, even given D ( P ) 7 " T(x). This difficulty is caused by the possible presence of idle chain subheads, which we now define. Definition. Suppose x E L E ~. T h e n x is said to be a s u b h e a d of L iff x ~ and T(x) ~ L. B y Corollary 1.2, T(x) = T(h(L)).

4.4.1 S u b h e a d Absence. We now argue t h a t the absence of idle chain subheads improves the implementability of (CD3). F u r t h e r benefits will become evident in Sections 6 and 7. THEOREM 4. I f n o s u b h e a d s exist on chains in ~ then (CD3) m a y be implem e n t e d as an Hbit( y) = 0 test. PROOF. Clearly, if H b i t ( y ) = 1, y ~ ~ , so y ~ OC. Now suppose D ( P ) 7 " T ( y ) and H b i t ( y ) = 0. T h e n either y E OC, and we are done, or y E chain(y) E ~. ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Referencing and Retention in Block-Structured Coroutines

275

Since T ( y ) E OC, y must either bc in 3~for be a subhead of chain(y). B o t h are impossible by assumption. 4.4.2 Subhead Creation. Idle chains with subheads are created when d e t a c h e s are done on instances not statically surrounding the currently operating instance. THEOREM 5. Suppose D(P) = w 7 " T(y) and a d e t a c h is done on y. Then chain(y) has no subheads iff w 7 " y. PROOF. Assume chain(y) is formed with no subheads. T h e n y E W a n d , for all z E chain(y), z 7 " y. In particular, w 7 " y. Now assume w 7 " y. Consider any z such t h a t w --** z --** y. B y Corollary 1.1, z 7 " y. Hence chain(y) has no subheads. [] 4.4.3 Preventing Subheads. B y T h e o r e m 5, idle chain subheads can be avoided, with no other loss of flexibility, by enforcing (CD3') D(P) ~ * y r a t h e r t h a n (CD3) D(P) 7 " T(y). This m a y be achieved, if desired, in one of two ways: (1) by adopting (CD3'), with implementation stat(y) 0 because of e. Otherwise, t(e) ~ * x, so x E ~ e t already by (AR7), a contradiction. [] ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Referencing and Retention in Block-Structured Coroutines

279

COROLLARY 7.1 I f x E 3¢~a n d ext(x) --- 0, r(x) a n d S a t are disjoint. PROOF. Follows directly from T h e o r e m 7 and (AR7).

[]

COROLLARY 7.2 I f x E H a n d ext(x) = 0, c h a i n ( x ) a n d ~¢cl are disjoint. PROOF. B y T h e o r e m 7, x ~ ~e~; hence x ~ Jc~. B y (AR3) and (AR5), chain(x) and ~¢c[ are then necessarily disjoint. [] COROLLARY 7.3 I f X E 9¢~ a n d ext(x) = 0, r(x) m a y be d e l e t e d , a n d , for e a c h ' s u b h e a d y E c h a i n ( x ) , ~(y) m a y be d e l e t e d if e x t ( y ) = 0 a n d t e r m i n a t e d otherwise. PROOF. B y Corollary 7.1, r(x) is disjoint from ~ e l and m a y be deleted. B y Corollary 7.2, y ~ ~¢cl for each subhead y E chain(x). Hence v(y) m a y be terminated. If e x t ( y ) = O, r ( y ) m a y then be deleted since y will t h e n be a head instance (of a singleton chain). 63

.~' Invariants

Before describing the operation of ~ ' in detail, we specify its desired behavior through a list of invariants t h a t are to be preserved (in addition to (LO1)-(LO4)): (RC1) (RC2) (RC3) (RC4)

64

for all e E 8, e÷ = nil V e÷ E 5P; for all x ~ ~, ext(x) = I{e E 81 t(D =~* x}l; for all L @ ~, e x t ( h ( L ) ) > 0; and for all x E Y,, (a) D ( x ) = x; (b) v(x) _C S,, and (c) if policy (b) is in effect, for all e E o~ such t h a t t(D = x, ~÷ = nil.

O p p o r t u n i t i e s Under .~'

Given properly maintained e x t count fields, the instance deletion and termination opportunities provided by T h e o r e m 7 and its corollaries m a y be exploited as follows. 6.4.1 Detection. T h e r e are three occasions upon which the conditions for ~ ' can apply. (1) r e m r e f e , with e + = x: if ext(x) is brought to zero and x ~ ~ , we m a y delete r(x) and terminate T(y) for each subhead y in chain(x). (2) d e t a c h a, with a evaluating to x: if ext(x) = O, we m a y again delete r(x) and terminate v(y) for each subhead y in the newly created chain(x). (3) t e r m i n a t e , with D ( P ) = x: if ext(x) = O, we m a y delete T(x); otherwise, we m a y terminate T(x). 6.4.2 Effects. T h e reference counting assumed under ~ ' requires certain effects in instance deletion and termination beyond those defined in Section 5.3. We sharpen these specifications here in preparation for their algorithmic accomplishm e n t in Section 6.5. (1) T(x) deletion: (a) For all e such t h a t t(e) ~ * x, i f e ¢ # nil and e÷ =~* x, r e m r e f e . ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

280

Gary Lindstrom and Mary Lou Sofia

(b) For all y ~ v(x), remove y from 5~. (2) v(x) t e r m i n a t i o n : (a) If ext(x) = 0, delete r(x). Otherwise: (b) U n d e r policy (b): (i) For all e such t h a t t(e) = x, r e m r e f e ; (ii) for all y such t h a t T ( y ) = x, delete r(y); and {iii) terminate x. (c) U n d e r policy (c): (i) For a l l y ~ Y-such t h a t T ( y ) = x, terminate v(y); and (ii) terminate x. 6.5 Implementing ~ ' T h e processes of T-tree deletion and termination specified above are highly recursive. N o t only are t h e y s t a t i c a l l y recursive in traversing v(x) b u t also d y n a m i c a l l y recursive due to r i p p l i n g effects. T h a t is, the deletion of v(x) m a y cause the deletion (or termination) of a disjoint v(y) to be triggered through a r e m r e f operation within r(x). Moreover, the termination of r(x) can cause under policy (c) the cascaded deletion of several subtrees of T(x) in unpredictable order. T h e s e effects can cause not only bookkeeping problems b u t also uncontrolled space requirements if not carefully implemented. 6.5.1 T h e W o r k l i s t W. For these reasons we i m p l e m e n t T-tree deletion and termination as cooperating algorithms processing a queue of instances needing their attention. We t e r m t h a t queue the w o r k l i s t W. Fortunately, all such n e e d y instances can relinquish their previous chain membership, so we can i m p l e m e n t W as a special pseudochain, with its front ( " h e a d " ) pointed to by W f r o n t and its rear by D ( W f r o n t ) . T h e n (1) if x E W with ext(x) = 0, v(x) is to be deleted; otherwise, v(x) is to be terminated. (2) We assume W is sorted such t h a t stat(x) >_ s t a t ( D ( x ) ) for x ~ W and x not at the front of W. 6.5.2 S e e d i n g W. Instances enter W through one of the three occasions specified in Section 6.4.1. B y examination of these conditions, we observe t h a t one c o m m o n algorithm suffices: q u e u e e h a i n (Figure 5). We assume t h a t each such p r o g r a m event causes a q u e u e c h a i n invocation, followed by p r o c e s s q u e u e . Rippled r e m r e f s m a y cause further W loading (via s c h e d u l e ) , but these are handled in due course by the same continuing p r o c e s s q u e u e execution. 6.5.3 R e p r e s e n t i n g v(x). We assume each instance x has two link fields, d e s c and sib, representing v(x) as follows. Suppose x has k descendants yi, each such t h a t T(yi) = x. T h e n s i b i - l ( d e s c ( x ) ) = yi,

1 ~ i 0 for 9 ' , a n d x will be m a r k e d u n d e r @". ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Referencing and Retention in Block-Structured Coroutines

291

8.3 Future Work

One omission in this work is the consideration of reference-valued parameters. I f , however, these are either excluded or made to obey CRF, our results stand. It may well be fruitful to explore design choices intermediate between this extreme and that of unrestrained reference passage via parameters. One approach m i g h t be the explicit declaration of which references can be exported or imported; such constructs are now being advocated as a means toward better program modularization. Another area for continuing work concerns the adaptation of these results to execution environments involving true concurrency [13]. Some preliminary studies have indicated that process reference counting is preferable to garbage collection, in light of the latter's apparently greater need for centralized control [18]. How scoping issues could be exploited in this setting remains unknown. Finally, additional work is merited on the notion of control discipline necessity given particular implementation strategies. This line of inquiry reverses that explored in this paper, in which sample disciplines were shown to be sufficient to safeguard the correctness of an implementation strategy [15]. With insights in this direction, important questions such as the class of BSCR programs for which 9" is superfluous might be approached. REFERENCES

1. BAKER, H.G. JR., AND HEWITT, C. The incremental garbage collection of processes. In Prec. ACM Syrup. on Artificial Intelligence and Programming Languages, Univ. Rochester, N.Y., Aug. 15-17, 1977. Published as combined issue: S I G P L A N Notices (ACM) 12, 8 (Aug. 1977), and S I G A R T Newsl. (ACM) 64 (Aug. 1977), 55-59. 2. BERRY, D.M., CHIRICA, L.M., JOHNSTON, J.B., MARTIN, D.F., AND SORKIN, A. Time required for reference count management in retention block-structured languages. Int. J. Comput. Inf. Sci. 7, 1 (1978), 11-64 (Part 1); 7, 2 (1978), 91-119 (Part 2). 3. BERRY, D.M., AND SORKIN,A. Time required for garbage collection in retention block-structured languages. Int. J. Comput. Inf. Sci. 7, 4 (1978), 361-404. 4. BOBROW,D.G., AND WEGBREIT, B. A model and stack implementation of multiple environments. Commun. A C M 16, 10 (Oct. 1973), 591-603. 5. CLINT, M. Program proving: Coroutines. Acta Inf. 2 (1973), 50-63. 6. CONWAY, M.E. Design of a separable transition-diagram compiler. Commun. A C M 6, 7 (July 1963), 396-408. 7. DAHL, O.-J. An approach to correctness proofs of semicoroutines. In Programming Methodology, D. Gries (Ed.), Springer-Verlag, New York, 1978, pp. 116-129. 8. DAHL, O.-J., MYHRHAUG, B., AND NYGAARD, K. SIMULA-67: Common base language. Publ. S2, Norwegian Computing Center, Oslo, 1968. 9. FRIEDMAN, D.P., AND WISE, D.S. CONS should not evaluate its arguments. Tech. Rep. 44, Dep. Computer Science, Indiana Univ., Bloomington, Ind., Nov. 1975. 10. GRISWOLD, R.E., AND HANSON, D.R. Language facilities for programmable backtracking. In Prec. ACM Syrup. on Artificial Intelligence and Programming Languages, Univ. Rochester, N.Y., Aug. 15-17, 1977. Published as combined issue: S I G P L A N Notices (ACM) 12, 8 (Aug. 1977), and S I G A R T Newsl. (ACM) 64 (Aug. 1977), 94-99. 11. HANSON, D.R., AND GRISWOLD, R.E. The SL5 procedure mechanism. Commun. A C M 21, 5 (May 1978), 392-400. 12. INGALLS, D. The Smalltalk-76 programming system. In Prec. 5th ACM Syrup. on Principles of Programming Languages, Tucson, Ariz., Jan. 1978, pp. 9-16. 13. KAHN, G., AND MAcQUEEN, D. Coroutines and networks of parallel processes. IRIA/LABORIA Res. Rep. 202, Le Chesnay, France, Nov. 1976. ACM Transactions on Programming Languages and Systems, VoL 3, No. 3, July 1981.

292

Gary Lindstrom and Mary Lou Sofia

14. KRIEG, B. A class of recursive coroutines. In I F I P Congress 74 (Software Booklet), NorthHolland, Amsterdam, 1974, pp. 408-412. 15. LINDSTROM, G., AND SOFFA, M.L. Control discipline necessity: Making the language as general as the implementation. In preparation. 16. McDERMOTT, D., AND SUSSMAN,G.J. The CONNIVER reference manual. MIT AI Lab. Memo. 259, MIT, Cambridge, Mass., May 1972. 17. MCILROY, M.D. Coroutines: Semantics in search of a syntax. Unpublished manuscript, 1968. 18. NOR1, A.K. A storage reclamation scheme for Applicative Multi-Processing System AMPS. M.S. thesis, Dep. Computer Science, Univ. Utah, Salt Lake City, Sept. 1979. 19. RANDELL, B., AND RUSSELL, L.J. Algol 60 Implementation. Academic Press, New York, 1964. 20. SCHORR,H., AND WAITE, W.M. An efficient machine-independent procedure for garbage collection in various list structures. Commun. A C M 10, 8 (Aug. 1967), 501-506. 21. VAN WIJNGAARDEN,A., MAILLOUX,B.J., PECK, J.E.L., KOSTER, C.H.A., SINTZOFF,M., LINDSEY, C.H., MEERTENS, LG.L.T., AND FISKER, R.G. Revised report on the algorithmic language Algol 68. A L G O L Bull. 36 (March 1974), suppl. 22. VANEK, L.I. Hierarchical coroutines: A mechanism for improved program structure. Tech. Rep. 99, Computer Systems Research Group, Univ. Toronto, Ontario, Feb. 1979. 23. WANG, A., AND DAHL, O.-J. Coroutine sequencing in a block-structured environment. B I T 11 (1971), 425-449. Received December 1979; revised September 1980 and January 1981; accepted January 1981

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.