Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int...

44
Chap 9 Run-time Storage the C program : c int x; abc(int y) oat z; atic int w; abc(z); malloc(20) { abc(3) t of 1. static var x 2. constant 3 ve 3. parameters y 4. return value 5. local variable z 6. dynamic allocation mal 7. static local variable

Transcript of Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int...

Page 1: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

Consider the C program :

static int x;int abc(int y){

float z;static int w;abc(z);malloc(20)

}

main {abc(3)

}

placement of 1. static var x 2. constant 3 recursive 3. parameters y calls 4. return value 5. local variable z 6. dynamic allocation malloc() 7. static local variable w

Page 2: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

- evolution : 1. static allocation

2. stack

3. heap

- Assume, we allocate/free one data area

at a time. Each data area may contain

one or more data objects.

Page 3: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.1 Static Allocation

- In FORTRAN and assembly languages.

- easy, originally

- In order to save space, use overlay.

e.g. equivalence classes in FORTRAN.• potentially dangerous

- static storage is for• global variables (fixed size)• literals• own (in Algol 60)• static and extern (in C)

- Conceptually, bind objects to absolute

addresses at compile time.

- For separately compiled programs,

binding can be delayed until link time.

Page 4: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.2 Stack Allocation

- For recursive procedures, we need a run-time stack.- The stack contains several activation records(ARs).- Each AR contains the local variables of a procedure.

• push AR when a procedure is called.• pop AR when a procedure returns.

Ex. ABCBC

C B

C B

A

Page 5: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• Contents of AR:1. parameters/return values2. local variables3. some pointers

Ex. proc P(a : integer) is b : real; c : array (1..10) of real; begin b := c(a) * 2.51; end

c

b

a

some pointers

28

86

5

0

- At compile time, we know the offset of each data object relative to the beginning of the AR.

- The offset information is stored in the symbol table.

Page 6: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

- Literals are stored in a static literal pool.- How about dynamic arrays? procedure P(a : integer) is b : array[1..a] of integer; begin end

We do not know the size of the array at compile time. Solution : <1> Each array type is represented by a dope vector(containing size + bounds). <2> Each dynamic array variable is represented by a pointer. Both <1> and <2> are uninitialized and on the stack.

pointer to bdope vector asome pointers

AR:

Page 7: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

At run time, when P is called, 1. initialize the dope vector; 2. allocate space just on top of stack; 3. initialize the pointer.

P(9) ( b array )

ptr 9 1 .. 9 a (=9)some pointers

:::

:::

..............................

- The compiler needs to generate code for 1, 2, and 3.

- The dynamic array is accessed indirectly through the pointer.

stack:

Page 8: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

- How about ¢static¢variables in C? Ex.

int a;void xyz(){ static int b = 0; b = b + 1; printf( b );}

main(){ xyz(); xyz(); xyz();} (what values are printed?)

Values of static variables are preservedacross calls.

- Solution: Static variables are treated like global variables.

Page 9: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

- Subroutine calls are last-call-first-return. So we can use a stack.

- Other features such as coroutines, interacting processes, shared variables are much more difficult.

Page 10: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.2.1 Displays

- How to address the AR?

Ex. pqrqpsr

:rspqrqp

• Need pointers to the ARs.

• One register per AR not feasible.

Page 11: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

- Consider

proc A

proc B

proc C

proc D

var x

x

ABCBCD

Note. At any instant, onlythe most recent ARs ofthe current procedureand the enclosing procare needed.Consider proc D above- We don’t need pointers to B or old C.

DCBCBA

D[3]D[2]

D[1]

Page 12: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• This is called static nesting.

• The stack can grow very big but the static nesting is quite shallow for ordinary programs.

•We can allocate one register for each nesting level. This set of registers are called displays (D[1], D[2], ).

See the previous slide.

•The display can be stored in memory, rather than registers.

Page 13: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• Upon procedure call/return, we need to adjust the display registers.

How?1st approach:

Save the entire display in the AR when a procedure is called.Restore display upon return.

– too much.2nd approach:

Save only the display register for the level of the called procedure. Upon return, restore that register.

Who saves and restores?Caller saves display register in callee’s AR.Callee restores it.

,

Page 14: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

Ex.proc A

proc B

proc C

proc D

ABCDBC

Show display.

Page 15: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.2.2 block-level vs. procedural-level AR- In Ada, Algol 60, C, and Ada/CS, we may declare variables within blocks as well as within procedures.

Procedure A is a : integer;begin begin b : integer; end begin c : integer; end end

- We may create a new AR for each block.(-) more displays(-) run-time overhead

- Or we may use procedural-level ARs. We may even overlay variables.

Page 16: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

Ex. procedure XYZ ( A, B : integer) is C : integer begin begin D, E : integer; begin F : integer; end end begin G, H : integer; end end

FEDCBA

G

H

some pointers

AR:

Page 17: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.3 Heap Allocation

• How to handle dynamic allocation? p = malloc( ) in C new(p) in Pascal

The dynamically allocated storage doesnot possess the last-allocated, first-freedproperty. So we cannot use a stack.

We have to use the heap.

• Allocation:1. explicit allocation

allocate in PL/1new(p) in Pascal and Ada

2. implicit allocationcons in LISP‘abc’ ‘def ‘ in SNOBOL

3. no allocation (in the language itself)malloc(20) in C

Page 18: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

Ex. dangling pointer problem

var p, q : ­real;

new( p );q := p;dispose( p );q­ := 1.0;

Page 19: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• The real problem: How to manage the returned storage?

1. No deallocation - good if most heap objects stay useful. - good if there is a really big virtual memory. - user could maintain a private free-list.

2. explicit deallocation free( ) in C dispose( ) in Pascal - Users free space explicitly; heap manager keeps track of free space. - dangling pointer problem Should the implementation check dangling pointers?

3. implicit deallocation(garbage collection) - The useless space is automatically recovered.

Page 20: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

- Three approaches to garbage collection:

1. single reference At most one pointer to any heap object. e.g. strings. Not good for complex linked structures.

2. reference count For each object, keep a count of the number of pointers to the object. Free the object when its count is 0.

Refcount

object

3. mark-sweep-compact - Find all global pointers (including those in stack). - Mark all heap objects reachable from the global pointers. - Free all unmarked heap objects. - Compact remaining objects.

cycles?

Page 21: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

globalvarsconstants

stack heap

garbage

::

....

....

....

....

....

....

....

Page 22: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• Compiler must generate enough information concerning where global pointers are.

• Run-time routines perform marking, sweeping, and compaction.

• Garbage collection is activated only when heap space is exhausted, not whenever references are created or destroyed.

• Easy for uniform languages, e.g. LISP. Difficult for complex languages,e.g.Ada.

• Compaction is used to avoid fragmentation.

Page 23: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• garbage collection for single-reference objects (e.g. Ada/CS strings) hand-shaking convention

pointers objects

• Sweep through heap objects. Keep the heap object if 1. it points to an AR in use. 2. the corresponding pointer in AR points back to the object.

• Slight chance for uncollected garbage

Page 24: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• Uninitialized pointers may be mistaken as a valid pointer. - initialize all pointers when they are created or - check validity when referencing• Managing heap space

- first-fit- best-fit- circular-first-fit

• boundary tag: for combining adajacent free chunks.

status

• Usually, there are only a few different sizes of allocated chunks. Use different heaps for differently-sized chunks(bit map).

Page 25: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.4 Program Layout

How to arrange object code in mainmemory?

heap

stack

static data

literals

code

static data

literals

code(read-only)

reserved

highest addr

lowest addr

library &separatelycompiledmodules

Page 26: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• There is a danger of collision of stack and heap. So we need to check collision whenever stack and heap storage is allocated.

• VAX and 8086 support segmented memory.

We can use 1 segment for code (read only)1 segment for stack1 segment for heapetc.

Page 27: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• operand stack

Ex. a + b * c + d / e

push apush bpush cmuladdpush dpush edivadd

operand stack

Page 28: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• operand stack

Some stack-oriented architectures usean operand stack, rather than registers,to evaluate expressions.

1. Can we use the run-time stack as operand stack?

No. Because we might invoke functions when evaluating expressions.

2. Allocate operand stack to a separate segment or to the reserved locations.

Sometimes, it is possible to determine the max depth of the operand stack.

Page 29: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• In load-and-go compilers, there is no explicit linking.

• How can we call a library routine?1. Make the library routine self-relocating.

All addressing within the libraryroutines is base-relative orPC-relative.

2. Use transfer vector for cross-modulereference.

There is one entry for each libraryroutine in the transfer vector. Allcalls to library routines are madeindirectly through the transfer vector.

(in literal pool) log routine

........................ log addr........................

call logmain program

transfer vector

Page 30: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

3. Load the whole set of library routines into fixed location, before compilation!

Applicable when the set of library routines is small.

The compiler can maintain a table of entry-point addresses.

No indirection.Due to the lack of relocation in load-

and-go compilers, program layout is different.

static data literals

heap

stackcode

librarymodules

reserved

highest addr

lowest addr

Page 31: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.5 static and dynamic chains

Ex.

proc Avar X; proc B var Y; proc C beginX + Y end begin call C end proc D begin call B end begin call D end

ADBC

CBDA

dynamicchain

staticchain

AP

Page 32: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

ADBC

• For returning from a procedure, we need a chain of call sequence. (dynamic chain)

• For referencing variables, we need a chain of scope nesting. (static chain)

Ex. Show how to reference X and Y in C.

• We also need an AP(activation pointer) that point to the topmost AR.

Page 33: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• If we cannot use display registers, then we need to maintain the static chain.

static chain»display

• To reference variables through static chain is slower than through display. But the performance is acceptable because

80% : local (AP) or global data (fixed) 17% : immediately enclosing scope

Page 34: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.6 formal procedures

• A proc may be passed as a parameter and is later activated. Ex.

proc E( ); proc A ( F: proc ) var x : integer; begin x := 1; F( ); end proc B( ); var x : integer proc D( ) begin write(x); end begin x := 2; A( D ); end begin B( );end

what is printed?

Page 35: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

EBAD

D

A

B

E

x=1

x=2

dynamic chain

staticchain

• If we follow dynamic chain to find x, 1 is printed. This is called dynamic binding. In dynamic binding, we use the environment where D is activated.

• If we follow static chain to find x, 2 is printed. This is called static binding. In static binding, we use the environment where the instance of D is created.

:.............:

:.............:

Page 36: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

- Only early LISP implementations use dynamic binding. Modern descendants of LISP use static binding.

- Algol 60 and its descendants all use static binding.

Page 37: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• How to implement static binding?

When A passes B to C, we need to passtwo things :

1. a pointer to B’s code2. a pointer to A’s AR

closure

C

BA

Page 38: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

For the previous example

E EB EBA

E

stack

B B

E E

Ax=2 x=2

x=1

:....... :.......

:.......

:

:

:

EBAD

D

A

B

E

This pointer isobtained fromthe closure of D.

Page 39: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• goto out of a formal procedureproc E( ) proc A( F:proc ) begin F( ); end proc B( ) proc D( ) begin goto L; which L? end begin A(D); L: ..... endbegin B( )end

EBADAt run time,1. Use static chain to determine B’s AR.2. Follow dynamic chain to pop all ARs above B’s AR.

D

A

B

E

Page 40: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

A more complicated example :proc E proc A( F : proc ) begin ifthen B(F) else F( ) end proc B ( F: proc ) proc D( ) begin end begin ifthen A(D) else F( ) endbegin B( )end EBA(D)B(D)D

DBABE

NB!

Page 41: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.6.2 Use display to implement formal procedure

• closure = code addr + display registers

• Need a pointer to the caller’s AR.– restore_AR

When proc A calls formal proc B,1. Save restore_AR in A’s AR.2. Save display registers in A’s AR.3. restore_AR := pointer to A’s AR4. Set display registers from B’s closure.5. Jump to B’s addr.

When formal proc. B returns,1. Use restore_AR to restore all display registers from A’s AR.2. Restore restore_AR from A’s AR.

Page 42: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

B¢s AR

A¢s ARold display registersold restore_AR

::

(new)restore_AR

AB

run-time stack

Page 43: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

• No extra cost for normal procedure calls.

• difficult to handle non-local goto’s. However, non-local goto’s are rare.

Page 44: Chap 9 Run-time Storage Consider the C program : static int x; int abc(int y) { float z; static int w;  abc(z);  malloc(20) } main {  abc(3)

Chap 9 Run-time Storage

Chap 9 Run-time Storage

§ 9.6.3 perspective

• Formal procedures are hard to understand.

• formal procedures in C

C is very flat.so closure = addr of code (in C)

• Ada allows no formal procedures al all.

• Formal procedures are useful in certain situations.