Top Banner
Louden, 2003 1 Chapter 8 - Control II: Procedures and Environments
53
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

Louden, 2003 1

Chapter 8 - Control II: Procedures and Environments

Page 2: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 2Chapter 8

Three major parts of a runtime environment: Static area allocated at load/startup time.

Examples: global/static variables and load-time constants.

Stack area for execution-time data that obeys a last-in first-out lifetime rule. Examples: method variables and temporaries.

Heap or dynamically allocated area for "fully dynamic" data, e.g. data allocated with new

Page 3: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 3Chapter 8

Procedure Overview When functions are “first class” data items themselves,

they can be dynamically created and used like values just like any other data structure. (e.g., Haskell curried functions, eval)

pass functions as arguments A procedure is called or activated. Activation record: collection of data needed to maintain a

single execution of a procedure. access to local and non-local references. Static or dynamic environment (depending on scoping)

must be accessible during runtime. When a procedure depends only on parameters and fixed

language features – closed form. The code for a function together with its defining

environment is called closure – as we can resolve all outstanding non-local environments.

Page 4: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 4

At seats:

Using what you understand about the call stack, what actions take place on call?

What actions take place on return?

Chapter 8

Page 5: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 5Chapter 8

Implementing “Simple” Subprograms

Caller responsibilities1. Save the execution status of the caller (calling

environment)

2. Carry out the parameter-passing process by putting the parameters somewhere that the called function can access.

3. Pass the return address of the caller to the callee

4. Transfer control to the callee

Page 6: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 6Chapter 8

Implementing “Simple” Subprograms Return Actions:

1. If it is a function, move the return value to a place the caller can get it

2. Restore the execution status of the caller

3. Transfer control back to the caller

Page 7: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 7Chapter 8

Implementing “Simple” Subprograms

Called routine must Create an activation record:

– local variables– return address– points to other environments– parameters

– See CSILM lesson “Call Stack” for an example

csilm.usu.edu, Browse Resources, CSILM Activities, Programming Languages, Call Stack

Page 8: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 8Chapter 8

Parameter Passing Aliases may be created Type checking parameters – for legality and

to pick between overloaded methods a reference parameter is a nonlocal variable the same data object passed for two

parameters CALL S(X,X) causes aliasing With aliasing, interesting problems in

optimizations occur. x+2

y++

x+2

If x and y are aliases, x+2 isn’t a common subexpression

Page 9: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 9Chapter 8

Models of Parameter Passing

Page 10: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 10Chapter 8

1. Pass-by-value (in mode)– Typically we copy the value in, but can do with a

constant reference pointer.– Parameters are viewed as local variables of the

procedure– Disadvantages of copy:

• Requires more storage (duplicated space)• Cost of the moves (if the parameter is large)

– Disadvantages of constant reference:• Must write-protect in the called subprogram or compiler

check that there are no assignments.• Accesses cost more (indirect addressing)

Page 11: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 11Chapter 8

2. Pass-by-result (out mode)– function return value(s)– Local’s value is passed back to the caller– Physical move is usually used (copy to call stack)– Disadvantages:

• If value is passed, time and space costs to copy• order dependence may be a problem (if output values

are aliased)

procedure sub1(y: int, z: int);{y=0;z=5;}sub1(x, x);– Value of x in the caller depends on order of assignments at

the return

Page 12: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 12Chapter 8

3. Inout mode– Pass by value-result (aka copy-in copy-

out or copy-restore) – Used to save cost of indirect access.

Physical move, both ways • value-result (or pass by copy)• Disadvantages

– ordering may be a problem with a call like doit(x,x)

– time/space issues– Need to know whether address is computed

again before copying back. doit(i,a[i])

Page 13: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 13Chapter 8

4.Pass by reference.Issues:

– passing is faster (as no data copy) formal parameter is local object of type pointer

If expression is passed as an in/out parameter: a temporary location may be passed(and then the copy is changed, not the original)

Disadvantages: – access slower as is indirect (always follow a pointer to

access), but passing is fast (only copy a pointer, not a whole structure)

– may make inadvertent changes to parameters

Page 14: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 14Chapter 8

5. Pass-by-name (Delayed evaluated parameters)– By textual substitution– parameter is evaluated everytime it is used, but

it is evaluated in the caller’s environment– Purpose: flexibility of late binding– costly

Thunks: a pass by name argument is implemented by a little procedure (called a thunk) which evaluates the argument.

A thunk is a method to evaluate an expression that is yet to be evaluated.

Page 15: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 15Chapter 8

Pass-by-name How is it like other methods?

• If actual is a scalar variable, it is pass-by-reference• If actual is a constant expression, it is pass-by-value• If actual is an array element, it is like nothing elsee.g. procedure sub1(x: int; y: int);beginx := 1; Seems like nothing is happeningy := 2; with first assignments but it isx := 2; y := 3;end;sub1(i, a[i]);

Page 16: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 16Chapter 8

Example: procedure R(var i,j: integer); begin m:boolean; m := true; i := i + 1; j := j + 1; end;

m := 2; for(i=0;i<10;i++) c[i]=10*i; R(m,c[m]);

pass by reference: adds 1 to m and c[2]Pass by name: adds 1 to m and c[3]

Page 17: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 17Chapter 8

Parameter Passing Methods

Design Considerations for Parameter Passing1. Efficiency

2. One-way or two-way– These two are in conflict with one another!– Good programming => limited access to

variables, which means one-way whenever possible

– Efficiency => pass by reference is fastest way to pass structures of significant size

– Also, functions should not allow reference parameters

Page 18: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 18Chapter 8

Languages and Environments Languages differ on where activation

records must go in the environment:– Fortran is static: all data, including activation

records, are statically allocated. (Each function has only one activation record—no recursion!)

– Functional languages (Scheme,ML) and some OO languages (Smalltalk) are heap-oriented: all (or almost all) data, including activation records, are allocated dynamically.

– Most languages are in between: data can go anywhere (depending on its properties); activation records go on the stack.

Page 19: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 19Chapter 8

Simple stack-based allocation Described in Chapter 5. Nested declarations are added to the stack

as their code blocks are entered, and removed as their code blocks are exited.

Example: Stack at Point 1:{ int x; int y; { int z; } { int w; // Point 1 }}

Note ,z has been removed at point 1 as have exited scope

wyx

Page 20: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 20Chapter 8

Example (C): main →q →pint x;void p( int y){ int i = x; char c; ...}void q ( int a){ int x; p(1);}main(){ q(2); return 0;}

Page 21: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 21Chapter 8

Local variable access using the ep In a typical language with a stack-based runtime

environment, the local declarations in a procedure are fixed at compile-time, both in size and in sequence.

This information can be used to speed up accesses to local variables, by precomputing these locations as offsets from the ep.

Then the local frame need not have a name-based lookup operation (unlike the symbol table).

In fact, names can be dispensed with altogether.

Page 22: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 22Chapter 8

Non-local variable access Requires that the environment be able to identify

frames representing enclosing scopes. Using the control link results in dynamic scope

(and also kills the fixed-offset property as you are not sure which method will contain the x. Thus, you can’t depend on a fixed location).

If procedures can't be nested (C, C++, Java), the enclosing scope is always locatable by other means: it is either global (accessed directly) or belongs to the current object.

If procedures can be nested, to maintain lexical scope a new link must be added to each frame: the access link, pointing to the activation of the defining environment of each procedure.

Page 23: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 23Chapter 8

Nested Subprograms

The process of locating a nonlocal reference:1. Find the correct activation record instance2. Determine the correct offset within that

activation record instance

May need to follow several links (access chaining)The number of links is known from compile time.If used stack of symbol tables, can count how many tables you had to search to find it.If used individual stacks for each value, you can record the nesting depth of each variable.

Page 24: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 24Chapter 8

Procedure values as pointer pairs Each procedure becomes a pair of pointers: a

code pointer (called the instruction pointer or ip in the text), and an environment pointer (ep in the text) pointing to the definition environment of the procedure (which will become the access link during a call).

Such an <ep,ip> pair is sometimes called a closure.

Page 25: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 25Chapter 8

The Process of Locating a Nonlocal Reference

Finding the offset is easy Finding the correct activation record

instance:– Static semantic rules guarantee that all

nonlocal variables that can be referenced have been allocated in some activation record instance that is on the stack when the reference is made

Page 26: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 26Chapter 8

Nested Subprograms

Technique 1 - Static Chains A static chain is a chain of static links that

connects certain activation record instances

The static link in an activation record instance for subprogram A points to one of the activation record instances of A's static parent

The static chain from an activation record instance connects it to all of its static ancestors

Page 27: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 27Chapter 8

Static Chains Show the static/dynamic chains when main →C →A →B →C

main ----- static_depth = 0A ----- static_depth = 1

B ----- static_depth = 2

C ----- static_depth = 1

Page 28: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 28Chapter 8

Nested Subprograms

Static Chain Maintenance– At the call :

• The activation record instance must be built• The dynamic link is just the old stack top pointer• The static link must point to the most recent ari of

the static parent (in most situations)

– Two Methods to set static chain:

1. Search the dynamic chain until the first ari for the static parent is found--easy, but slow

Page 29: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 29Chapter 8

Nested Subprograms2. Treat procedure calls and definitions like

variable references and definitions (have the compiler compute the nesting depth, or number of enclosing scopes between the caller and the procedure that declared the called procedure; store this nesting depth and send it with the call)– e.g. Look at MAIN_2 and the stack contents. At the

call to SUB1 in SUB3, this nesting depth is 1, which is sent to SUB1 with the call. The static link in the new ari for SUB1 is set to point to the ari that is pointed to by the second static link in the static chain from the ari for SUB3

Page 30: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 30Chapter 8

Nested Subprograms Evaluation of the Static Chain Method

– Problems:

1. A nonlocal reference is slow if the number of scopes between the reference and the declaration of the referenced variable is large

2. Time-critical code is difficult, because the costs of nonlocal references are not equal, and can change with code upgrades and fixes

Page 31: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 31Chapter 8

Nested Subprograms

Technique 2 (for locating non-local variables with static scope) - Displays– The idea: Put the static links in a separate

stack called a display. The entries in the display are pointers to the ari's that have the variables in the referencing environment.

– Represent references as

(display_offset, local_offset)

where display_offset is the same as chain_offset– Can access via computation. display offset

of 10 is one lookup (not a chain of length 10)

Page 32: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 32Chapter 8

Main – level 0

q level 3

p

p level1

s level 2

r level 2

t level 1

Page 33: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 33Chapter 8

main

t

s

q

100 Level 0

200 Level 1

300 Level 2

400 Level 3

main-> t -> s-> q

When s calls q, a single element is added to the table.

100

200

300

400

Stack is shown growing downwards.Display contains pointers to eachactivation record at each reachable level

Page 34: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 34

At your seats…

Why do we do this? This seems well and good – but how do

we keep it current?

Chapter 8

Page 35: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 35Chapter 8

main

t

s

q

100 Level 0

500 Level 1

300 Level 2

400 Level 3

main-> t -> s-> q-> p

When q calls p, a new level 1 entry is needed.Store the old one, so you can get it back.Level 2 and level 3 are unused (but unchanged)

100

200

300

400

p

old level 1 is 200500

Page 36: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 36Chapter 8

main

t

s

q

100 Level 1

600 Level 2

300 Level 3

400 Level 4

main-> t -> s-> q-> p->t

When p calls t, a new level 2 entry is neededLevel 3 and level 4 are unused (but unchanged)

100

200

300

400

p

old level 2 is 200

500old level 2 is 500

t 600

Page 37: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 37Chapter 8

main

t

s

q

100 Level 1

600 Level 2

300 Level 3

400 Level 4

main-> t -> s-> q-> p->t

When p calls t, a new level 2 entry is neededLevel 3 and level 4 are unused (but unchanged)

100

200

300

400

p

old level 2 is 200

500old level 2 is 500

t 600

Page 38: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 38Chapter 8

Blocks

Two Methods:1. Treat blocks as parameterless subprograms– Use activation records

2. Allocate locals on top of the ari of the subprogram

– Must use a different method to access locals– A little more work for the compiler writer

Page 39: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 39Chapter 8

Implementing Dynamic Scoping

1. Deep Access (search) - nonlocal references are found by searching the activation record instances on the dynamic chain – Length of chain cannot be statically

determined– Every activation record instance must have

variable names recorded

Page 40: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 40Chapter 8

Implementing Dynamic Scoping

2. Shallow Access - put locals in a central place

How implemented?a. One stack for each variable name

b. Central referencing table with an entry for each variable name

At subprogram entry, add location for each variable.

At subprogram exit, remove location for each variable.

Page 41: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 41Chapter 8

Using Shallow Access to Implement Dynamic Scoping

Page 42: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 42Chapter 8

Parameter Passing Conventions Actual/Formal Parameter Correspondence:1. Positional (this is what we are used to)2. Keyword

– e.g. SORT(LIST => A, LENGTH => N);– Advantage: order is irrelevant– Disadvantage: user must know the formal parameter’s names

3. Default Values:e.g. procedure SORT(LIST : LIST_TYPE;

LENGTH : INTEGER := 100); ...SORT(LIST => A);

Page 43: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 43Chapter 8

Overloaded Subprograms

Def: An overloaded subprogram is one that has the same name as another subprogram in the same referencing environment

C++ and Ada have overloaded subprograms built-in, and users can write their own overloaded subprograms

Overloaded subprograms provide ad hoc (non-generalizable) polymorphism

Page 44: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 44Chapter 8

Generic Subprograms Analogy: Would you rather have:

– Vacuum that can adjust to any carpet height versus – A different vacuum for each type of carpet.

A generic or polymorphic subprogram is one (not many) subprogram that takes parameters of different types on different activations

A subprogram that takes a generic parameter needs to figure out what type was passed (Haskell)

Page 45: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 45Chapter 8

Separate & Independent Compilation Def: Independent compilation is

compilation of some of the units of a program separately from the rest of the program, without the benefit of interface information

Def: Separate compilation is compilation of some of the units of a program separately from the rest of the program, using interface information to check the correctness of the interface between the two parts.

Page 46: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 46Chapter 8

Memory ManagementBenefit (of system controlled storage management): ability to delay the binding of a storage segment's size and/or location reuse of a storage segment for different jobs (from system supervisor

point of view) reuse of storage for different data structures increased generality, not have to specify maximum data structure size dynamic data structures recursive procedures - garbage collection is automatic Adv/Disadv of programmer controlled storage management Disadvantage: burden on programmer & may interfere with necessary

system controlMay lead to subtle errorsMay interfere with system-controlled storage management

Advantage: difficult for system to determine when storage may be most effectively allocated and freed

Page 47: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 47Chapter 8

Heap management– Single-size cells vs. variable-size cells– Reference counters (eager approach) vs.

garbage collection (lazy approach)

1. Reference counters: maintain a counter in every cell that store the number of pointers currently pointing at the cell

– Disadvantages: space required, complications for cells connected circularly

Expensive - when making a pointer assignment p=q

1. decrement count for old value of p

2. if 0, return to free storage. Check if contains references to other blocks. Could be recursive

3. do pointer assignment

4. Increment reference count for q

Page 48: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 48Chapter 8

One-bit reference counting

Another variation on reference counting, called one-bit reference counting, uses a single bit flag to indicate whether each object has either "one" or "many" references.

If a reference to an object with "one" reference is removed, then the object can be recycled.

If an object has "many" references, then removing references does not change this, and that object will never be recycled. It is possible to store the flag as part of the pointer to the object, so no additional space is required in each object to store the count.

One-bit reference counting is effective in practice because most actual objects have a reference count of one.

Page 49: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 49Chapter 8

2. Garbage collection: allocate until all available cells allocated; then begin gathering all garbage

– Every heap cell has an extra bit used by collection algorithm

– All cells initially set to garbage– All pointers traced into heap, and reachable cells

marked as not garbage– All garbage cells returned to list of available cells

Disadvantages: when you need it most, it works worst (takes most time when program needs most of cells in heap)

Page 50: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 50Chapter 8

Mark-Sweep - Java uses In a mark-sweep collection, the collector first examines the program

variables; any blocks of memory pointed to are added to a list of blocks to be examined.

For each block on that list, it sets a flag (the mark) on the block to show that it is still required, and also that it has been processed. It also adds to the list any blocks pointed to by that block that have not yet been marked. In this way, all blocks that can be reached by the program are marked.

In the second phase, the collector sweeps all allocated memory, searching for blocks that have not been marked. If it finds any, it returns them to the allocator for reuse

Can find circular references. Easy if regular use of pointers (Like in LISP) All elements must be reachable by a chain of pointers which begins

outside the heap Have to be able to know where all pointers are - both inside the heap

and outside. How can a chain be followed from a pointer if there is no predefined location for that pointer in the pointed-to cell?

Page 51: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 51Chapter 8

Conservative garbage collection Although garbage collection was first invented in 1958, many

languages have been designed and implemented without the possibility of garbage collection in mind. It is usually difficult to add normal garbage collection to such a system, but there is a technique, known as conservative garbage collection, that can be used.

The usual problem with such a language is that it doesn't provide the collector with information about the data types, and the collector cannot therefore determine what is a pointer and what isn't.

A conservative collector assumes that anything might be a pointer. It regards any data value that looks like a pointer to or into a block of allocated memory as preventing the recycling of that block.

You might think that conservative garbage collection could easily perform quite poorly, leaving a lot of garbage uncollected. In practice, it does quite well, and there are refinements that improve matters further.

Because references are ambiguous, some objects may be retained despite being actually unreachable. In practice, this happens rarely, and refinements such as black-listing can further reduce the odds.

Page 52: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 52Chapter 8

Incremental Garbage Collection Older garbage collection algorithms relied on being able to

start collection and continue working until the collection was complete, without interruption. This makes many interactive systems pause during collection, and makes the presence of garbage collection obtrusive.

Fortunately, there are modern techniques (known as incremental collection) to allow garbage collection to be performed in a series of small steps while the program is never stopped for long. In this context, the program that uses and modifies the blocks is sometimes known as the mutator. While the collector is trying to determine which blocks of memory are reachable by the mutator, the mutator is busily allocating new blocks, modifying old blocks, and changing the set of blocks it is actually looking at.

Page 53: Louden, 20031 Chapter 8 - Control II: Procedures and Environments.

K. Louden, Programming Languages 53Chapter 8

Heap Storage Management - Variable Sized Elements Memory operations Initially one large block Free space list, as space is recovered allocate from free list: first fit, best fit, worst fit compact: maintain a length of each block recover via explicit, garbage collection or reference counts

Need length of each to locate pieces and coalesce fragmentation partial compaction (coalescing of adjacent free blocks)

full compaction (move blocks) Show how