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)

Slides:



Advertisements
Similar presentations
Implementing Subprograms
Advertisements

(1) ICS 313: Programming Language Theory Chapter 10: Implementing Subprograms.
CS 326 Programming Languages, Concepts and Implementation Instructor: Mircea Nicolescu Lecture 18.
Chapter 8 Runtime Support. How program structures are implemented in a computer memory? The evolution of programming language design has led to the creation.
Chapter 9 Subprogram Control Consider program as a tree- –Each parent calls (transfers control to) child –Parent resumes when child completes –Copy rule.
ISBN Chapter 10 Implementing Subprograms.
1 Storage Registers vs. memory Access to registers is much faster than access to memory Goal: store as much data as possible in registers Limitations/considerations:
1 Chapter 7: Runtime Environments. int * larger (int a, int b) { if (a > b) return &a; //wrong else return &b; //wrong } int * larger (int *a, int *b)
Memory Allocation. Three kinds of memory Fixed memory Stack memory Heap memory.
ISBN Chapter 10 Implementing Subprograms.
ISBN Chapter 10 Implementing Subprograms.
Honors Compilers Addressing of Local Variables Mar 19 th, 2002.
Chapter 10 Storage Management Implementation details beyond programmer’s control Storage/CPU time trade-off Binding times to storage.
Run time vs. Compile time
Semantics of Calls and Returns
The environment of the computation Declarations introduce names that denote entities. At execution-time, entities are bound to values or to locations:
1 CSCI 360 Survey Of Programming Languages 9 – Implementing Subprograms Spring, 2008 Doug L Hoffman, PhD.
1 Run time vs. Compile time The compiler must generate code to handle issues that arise at run time Representation of various data types Procedure linkage.
Chapter 10 Implementing Subprograms. Copyright © 2007 Addison-Wesley. All rights reserved. 1–2 Semantics of Call and Return The subprogram call and return.
COP4020 Programming Languages
Chapter 7: Runtime Environment –Run time memory organization. We need to use memory to store: –code –static data (global variables) –dynamic data objects.
ISBN Chapter 10 Implementing Subprograms.
Runtime Environments What is in the memory? Runtime Environment2 Outline Memory organization during program execution Static runtime environments.
Runtime Environments Compiler Construction Chapter 7.
Programming Language Principles Lecture 24 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines.
Compiler Construction
1 Names, Scopes and Bindings Aaron Bloomfield CS 415 Fall
Chapter 10 Implementing Subprograms. Copyright © 2012 Addison-Wesley. All rights reserved.1-2 Chapter 10 Topics The General Semantics of Calls and Returns.
1 Copyright © 1998 by Addison Wesley Longman, Inc. Chapter 9 Def: The subprogram call and return operations of a language are together called its subprogram.
Basic Semantics Associating meaning with language entities.
Runtime Environments. Support of Execution  Activation Tree  Control Stack  Scope  Binding of Names –Data object (values in storage) –Environment.
CSC3315 (Spring 2008)1 CSC 3315 Subprograms Hamid Harroud School of Science and Engineering, Akhawayn University
1 Records Record aggregate of data elements –Possibly heterogeneous –Elements/slots are identified by names –Elements in same fixed order in all records.
CS 326 Programming Languages, Concepts and Implementation Instructor: Mircea Nicolescu Lecture 9.
ISBN Chapter 10 Implementing Subprograms.
Implementing Subprograms What actions must take place when subprograms are called and when they terminate? –calling a subprogram has several associated.
COMP3190: Principle of Programming Languages
RUN-Time Organization Compiler phase— Before writing a code generator, we must decide how to marshal the resources of the target machine (instructions,
國立台灣大學 資訊工程學系 薛智文 98 Spring Run Time Environments (textbook ch# 7.1–7.3 )
CSC 8505 Compiler Construction Runtime Environments.
1 Chapter 10 © 2002 by Addison Wesley Longman, Inc The General Semantics of Calls and Returns - Def: The subprogram call and return operations of.
7. Runtime Environments Zhang Zhizheng
RUNTIME ENVIRONMENT AND VARIABLE BINDINGS How to manage local variables.
Chapter 10 Implementing Subprograms. Copyright © 2012 Addison-Wesley. All rights reserved.1-2 Chapter 10 Topics The General Semantics of Calls and Returns.
10-1 Chapter 10: Implementing Subprograms The General Semantics of Calls and Returns Implementing “Simple” Subprograms Implementing Subprograms with Stack-Dynamic.
ISBN Chapter 10 Implementing Subprograms.
Implementing Subprograms
Subprograms - implementation. Calling a subprogram  transferring control to a subprogram: save conditions in calling program pass parameters allocate.
ISBN Chapter 10 Implementing Subprograms.
1 Compiler Construction Run-time Environments,. 2 Run-Time Environments (Chapter 7) Continued: Access to No-local Names.
ISBN Chapter 10 Implementing Subprograms.
Runtime Environments Chapter 7. Support of Execution  Activation Tree  Control Stack  Scope  Binding of Names –Data object (values in storage) –Environment.
Implementing Subprograms
Storage Allocation Mechanisms
Chapter 10 : Implementing Subprograms
Implementing Subprograms Chapter 10
Implementing Subprograms
Implementing Subprograms
Implementing Subprograms
Chapter 10: Implementing Subprograms Sangho Ha
Implementing Subprograms
Implementing Subprograms
Implementing Subprograms
Topic 3-b Run-Time Environment
Runtime Environments What is in the memory?.
Where is all the knowledge we lost with information? T. S. Eliot
RUN-TIME STORAGE Chuen-Liang Chen Department of Computer Science
Implementing Subprograms
Implementing Subprograms
Chapter 10 Def: The subprogram call and return operations of
Presentation transcript:

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

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.

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.

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. A    B    C   B    C C B C B A

Chap 9 Run-time Storage Contents of AR: 1. parameters/return values 2. local variables 3. 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 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.

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 : Each array type is represented by a dope vector(containing size + bounds). Each dynamic array variable is represented by a pointer. Both and are uninitialized and on the stack. pointer to b dope vector a some pointers AR:

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 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:

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(  ); } (what values are printed?) Values of static variables are preserved across calls. - Solution: Static variables are treated like global variables.

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.

Chap 9 Run-time Storage § Displays - How to address the AR? Ex. p   q    r    q    p    s    r  :rspqrqp:rspqrqp Need pointers to the ARs. One register per AR  not feasible.

Chap 9 Run-time Storage - Consider proc A proc B proc C proc D var x  x  ABCBCDABCBCD Note. At any instant, only the most recent ARs of the current procedure and the enclosing proc are needed. Consider proc D above - We don ’ t need pointers to B or old C. DCBCBADCBCBA D[3] D[2] D[1]

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.

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.,

Chap 9 Run-time Storage Ex. proc A proc B proc C proc D ABCDBCABCDBC Show display.

Chap 9 Run-time Storage § 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.

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 F E D C B A G H some pointers AR:

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 does not possess the last-allocated, first-freed property. So we cannot use a stack. We have to use the heap. Allocation: 1. explicit allocation allocate in PL/1 new(p) in Pascal and Ada 2. implicit allocation cons in LISP ‘ abc ’  ‘ def ‘ in SNOBOL 3. no allocation (in the language itself) malloc(20) in C

Chap 9 Run-time Storage Ex. dangling pointer problem var p, q : ­ real; new( p ); q := p; dispose( p ); q ­ := 1.0;

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.

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. Ref count 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?

Chap 9 Run-time Storage global vars constants stackheap garbage ::::....

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.

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

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).

Chap 9 Run-time Storage § 9.4 Program Layout How to arrange object code in main memory? heap stack static data literals code static data literals code(read-only) reserved highest addr lowest addr library & separately compiled modules  

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 stack 1 segment for heap etc.

Chap 9 Run-time Storage operand stack Ex. a + b * c + d / e push a push b push c mul add push d push e div add operand stack

Chap 9 Run-time Storage operand stack Some stack-oriented architectures use an 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.

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 library routines is base-relative or PC-relative. 2. Use transfer vector for cross-module reference. There is one entry for each library routine in the transfer vector. All calls to library routines are made indirectly through the transfer vector. (in literal pool) log routine log addr call log main program transfer vector

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   stack code library modules reserved highest addr lowest addr

Chap 9 Run-time Storage § 9.5 static and dynamic chains Ex. proc A var X; proc B var Y; proc C begin  X + Y  end begin call C end proc D begin call B end begin call D end ADBCADBC CBDACBDA dynamic chain static chain AP

Chap 9 Run-time Storage A    D    B    C 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.

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

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?

Chap 9 Run-time Storage EBADEBAD D A B E x=1 x=2 dynamic chain static chain 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. : : :

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.

Chap 9 Run-time Storage How to implement static binding? When A passes B to C, we need to pass two things : 1. a pointer to B ’ s code 2. a pointer to A ’ s AR closure C B A

Chap 9 Run-time Storage For the previous example E E  BE  B  A E stack B B E E A x=2 x=1 : : : : E  B  A  D D A B E This pointer is obtained from the closure of D.

Chap 9 Run-time Storage goto out of a formal procedure proc E( ) proc A( F:proc ) begin F( ); end proc B( ) proc D( ) begin goto L; which L? end begin A(D); L:..... end begin B( ) end E  B  A  D At 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

Chap 9 Run-time Storage A more complicated example : proc E proc A( F : proc ) begin if  then B(F) else F( ) end proc B ( F: proc ) proc D( ) begin  end begin if  then A(D) else F( ) end begin B( ) end E    B    A(D)    B(D)    D DBABEDBABE NB!

Chap 9 Run-time Storage § 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 AR 4. 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.

Chap 9 Run-time Storage B ¢ s AR A ¢ s AR old display registers old restore_AR :::: (new) restore_AR A  B run-time stack

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.

Chap 9 Run-time Storage § 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.