A Binding Question! Variables are bound (dynamically) to values Subprogram Activation! Those values must be stored somewhere! Therefore, variables must somehow be bound to memory locations! How? Function Activations! The lifetime of one execution of a function, from call to corresponding return, is called an activation of the function! When each activation has its own binding of a variable to a memory locations, it is an activation-specific variable! (Also called dynamic or automatic) Block Activations! For block constructs that contain code, we can speak of an activation of the block! The lifetime of one execution of the block! A variable might be specific to an activation of a particular block within a function: int fact(int n) { if (n=0) then return 1; else return fact(n-1)*n; Other Lifetimes For Variables! Most imperative languages have a way to declare a variable that is bound to a single memory location for the entire runtime! Obvious binding solution: static allocation (classically, the loader allocates these) Scope And Lifetime Differ! In most modern languages, variables with local scope have activation-specific lifetimes, at least by default! However, these two aspects can be separated, as in C: int count = 0; int nextcount() { count = count + 1; return count; int nextcount() { static int count = 0; count = count + 1; return count;
Other Lifetimes For Variables! Object-oriented languages use variables whose lifetimes are associated with object lifetimes! Some languages have variables whose values are persistent: they last across multiple executions of the program! Today, we will focus on activation-specific variables Subprogram Activation! General Semantics of Calls and Returns! Implementing Subprograms! Static Local Variables and Subprograms! Stack-Dynamic Local Variables! Scope Issues - Non-local Variable Access! Dynamically Scoped Languages! Nested Subprograms Blocks Subprogram Activation! Subprogam Definition! Defines interface and actions of subprogram! Subprogram Call! Explicit request that specific subprogram be executed! Active Subprogram! Subprogram that has been called, but has not completed its execution! Application can have multiple active subprograms! Subprogram Linkage of a Language! The subprogram call and return operations Subprogram Activation! Program Linkage! Call Semantics: Save the execution status of the caller Carry out the parameter-passing process Pass the return address to the callee Transfer control to the callee! Return Semantics: For pass-by-value-result parameters move formal parameter values into corresponding actual parameters For functions move functional value to a place the caller can access it Restore the execution status of the caller Transfer control back to the caller s! Language implementations usually allocate all the activation-specific variables of a function together as an activation record! The activation record also contains other activation-specific data, such as! Return address: where to go in the program when this activation returns! Link to caller!s activation record: more about this in a moment Block s! When a block is entered, space must be found for the local variables of that block! Various possibilities:! Preallocate in the containing function!s activation record! Extend the function!s activation record when the block is entered (and revert when exited)! Allocate separate block activation records! Our illustrations will show the first option
Subprogram Activation! (at a minimum)! Subprogram Code! Local Variables! Parameters! Functional value (return value)! Return address!! Layout of non-code storage! Instance (ARI)! Concrete example of an activation record! Collection of data for a particular activation int fun1(float x, int y) { const int IVAL = 2; static int fval = 10; float list[4]; int n = IVAL; return 20*x+list[n]; int fun2(int a) { float b; fun1(b, a); int fun3(float r) { int s, t; s = fun2(s); int main() { float p, r; r = fun3(p);! Static Local Variables and Subprograms main() Application Stack Application Code fun1() Application Memory fun2() fun3() main ARI fun1 ARI fun2 ARI Return Address Return Value Parameters Local Variables fun3 ARI! Static Local Variables and Subprograms! Provides Fast Access and Execution All memory for application and subprograms allocated at load time Compiler can determine addresses at compile time Linker can determine all offsets at link time! Can waste memory Functions might never be called Multiple functions may need large ARI (for array) but only one will ever be active at a time! Cannot Implement Recursion Only a single instance of a subprogram may be active at a time Stacks Of s! To support recursion, we need to allocate a new activation record for each activation! Dynamic allocation: activation record allocated when function is called! For many languages, like C, it can be deallocated when the function returns! A stack of activation records: stack frames pushed on call, popped on return
! Stack-Dynamic Local Variables! More Complex Implementation Compiler must generate code for implicit allocation and deallocation of local variables Recursion must be supported Adds possibility of multiple simultaneous activations mat is static but its size may be dynamic! ARI must be dynamically created when subprogram is called (invoked)! Application Memory Partitioning Static Storage Dynamic Storage Subprogram Code Segments and System Code Segments Program Memory application stack stack growth free space (available for use) heap growth application heap heap bottom Start of Stack Block Allocated by subprogram invocation End of Stack Block Allocated by new operator! Code Segment for Subprogram! Executable Subprogram Code! Subprogram int fun1(float x, int y) { const int IVAL = 2; static int fval = 10; float list[4]; int n = IVAL; return 20*x+list[n]; Information concerning the current call (invocation) of subprogram fun1 is contained in its activation record.! Code Segment for Subprogram fun1! Code produced by compiler for subprogram Prologue Executable Subprogram Code Epilogue 20 10 2 Housekeeping code to create an activation record Executable Code for each Subprogram Statement Housekeeping code to delete the activation record Storage for Constants (reverse order)! Memory Organization During Execution! Memory Organization During Execution System Data stack chain pointer dynamic link Program (old stack Call Sequence: pointer) Return point location OpSys! main() Return Value main()! fun3() Formal Parameters fun3()! fun2() fun2()! fun1() Local Variables Temporaries for Expression Evaluation Temporaries for Parameter Transmission Subprogram Code Segments and System Code Segments Activation record storage Activation record storage Activation record storage Activation record storage Free Space application application heap heap Start of Stack Block System Data stack ARI chain of Parent pointer dynamic ARI of Caller link (old stack pointer) Old Return Prog point Counter location (PC) Return int fun1 Value Formal float Parameters x int y (reverse order) float Local Variables list[0] float list[1] float list[2] float list[3] Temporaries for Expression int n = 2 Evaluation Temporaries for Expression Temporaries for Parameter Evaluation and Parameter Transmission Transmission int fun1(float x, int y) { const int IVAL = 2; static int fval = 10; float list[4]; int n = IVAL; return 20*x+list[n];
! Subprogram! Block of storage containing local objects Local variables are accessed by their offset from the beginning of the activation record (local_offset) Compiler can determine local offset of a local variable! Template! s are Dynamic! Each invocation of subprogram results in! Creation of a new activation record! Static code generated by compiler is associated with the new activation record Data Structure of Compiler binds each identifier in subprogram with a storage location offset in activation record Template is stored in Code Segment Prologue fun1 Code Segment Static Storage fun1 fun1 fun1 Dynamic Storage! s Support Recursion int fact(int x) { if (x == 1) return 1; else return x * fact(x-1); Sample Call: fact(3) Scoping Issues : Non-Local Variable Access Dynamic Chains fact() Code Segment Static Storage fact(3) fact(2) fact(1) Dynamic Storage Successive invocations of subprogram Scope and s! First - Quick Review of Scope! Dynamic scope: Scope is determined by the execution of program! Static scope: Scope is dependent on the syntax of the program! Static Nested Scope: A variable is accessible in the function it is declared in, and all procedures internal to that function, except a new declaration of that variable name in an internal function will eliminate the new variable's scope from the scope of the outer variable.! Variable declared in function is local to function Scope and s! Two pointers manage scope in AR! Pointer (DL) Points to activation record that called (invoked) the current activation record! Pointer (SL) Points to the activation record that is global (parent) to the current activation record. Activation record of the subprogram containing the declaration of this subprogram.
Dynamically Scoped Languages!! Points to activation record of the caller! Used for returning from the subprogram! Used to access non-locals in Dynamic Scoping! Frequently implemented as old stack pointer! Dynamic Chain! Collection of dynamic links in the stack! Call Chain Dynamically Scoped Languages () () call call call () () () Scope Sub_S Dynamically Scoped Languages () () call call call () Dynamic Chain for Dynamic Chain for Scope Sub_S Dynamically Scoped Languages! Deep Access! Nonlocal references found on dynamic chain Length of chain cannot be statically determined Every ARI must have variable names! Shallow Access! Put locals in central place! Can be one stack for each variable name! Central table with entry for each variable name Dynamically Scoped Languages Scoping Issues : Non-Local Variable Access Static Chains and Displays
! Nested Subprograms! 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! Locating Nonlocal Variables! Find the correct activation record instance! Determine the correct offset within that ARI! Pointer (SL)! Points to the activation record that is global (parent) to the current activation record.! The activation record of the subprogram containing the declaration of this subprogram.! Static Chain! A chain of static links that connect hierarchically related activation record instances! Chain of static links that connects activation record instances based on static ancestors.! Static Chain! Compiler knows static structure! Chains can be generated at compile time (not run-time).! Static Depth! Number of static levels representing the nesting level of the scope of interest.! References for non-local variables are obtained by following the static chain.! Non-Local reference can be slow if static depth is large. (Consistant, but slow)! Static Chain! Chain Offset (Nesting Depth) Difference between the static depth of a reference (to a variable) and the static depth of the scope in which it was declared.! Local Offset Offset in the activation record of the refernced variable.! Reference Pairs for Nonlocal Variables (chain_offset, local_offset) () () call call call () () () Scope Sub_S and exist, but not within static scope of SubS() () () call call call () () () Scope Sub_S
() () call call call () Static Chain for Dynamic Chain for Static Chain for Dynamic Chain for! Static Chain Maintenance! Build! is the old! is most recent ARI of static parent Search the dynamic chain until the first ARI for the static parent is found--easy, but slow Store Nesting Depth from Definition to Caller Transit Caller Static Chain to appropriate depth! Issues with Static Chain! Slow nonlocal reference if the number of scopes between reference and declaration is large! Time-critical code is difficult to verify Costs of nonlocal references are not equal Costs can an change with code upgrades and fixes Static Scope and Displays! Displays! Place static links in a separate stack that is part of the activation record. Previous level!s activation record!s display is copied and a pointer to the new activation record is pushed.! Entries are direct links to activation records of declarations.! Display Reference Pairs (display_offset, local_offset) Display Offset is same as Chain Offset Static Scope and Displays! Reference Mechanics:! Use display offset to get pointer to activation record of interest! Use local offset to get to the variable within that particular activation record.! Always a two-step process, independent of static nesting depth! Display can be kept in registers! If there are enough! Speeds up access and maintenance Static Scope and Displays! Comparing Static Chain and Display! References to locals Not much difference! References to nonlocals If it is one level away, they are equal If it is farther away, the display is faster! Display is better for time-critical code All nonlocal references cost the same
Static Scope and Displays! Subprogram Calls! One or two levels of depth, static chain is faster! Greater than two levels, display is faster! Subprogram Returns! Both have fixed time, but the static chain is slightly faster! Static chain is better, unless the display can be kept in registers Blocks! Code Blocks can define local scoping! Implementation can vary! Treat blocks as parameterless subprograms Use activation records! Allocate locals in the subprogram ARI { int temp = x; x = y; y = temp;