190 likes | 196 Views
The environment of the computation. Declarations introduce names that denote entities. At execution-time, entities are bound to values or to locations: name value (functional) name location value (imperative)
E N D
The environment of the computation • Declarations introduce names that denote entities. • At execution-time, entities are bound to values or to locations: name value (functional) name location value (imperative) • Value binding takes place during function invocation • Namesare boundtomemorylocationson scope entry.Locationsare bound tovaluesby assignment. • Compiler establishes symbolic mapping between names and locations: name offsetfromrun-time pointer • Run-time pointer is stack frame, TOC entry, static link, etc.
Run-time organization • Each subprogram invocation creates an activation record. • Recursion imposes stack allocation (all languages today) • Activation record hold actuals, linkage information, saved registers, local entities. • caller: place actuals on stack, return address, linkage information, then transfer control to callee. • Prologue: save registers, allocate space for locals • Epilogue: place return value in register or stack position, update actuals, restore registers, then transfer control to caller. • Binding of locations: actuals and locals are at fixed offsets from frame pointers • complications: variable no. of actuals, dynamic objects.
Activation record layout actual actual Handled by caller Frame pointer Return addr Save area local Handled by callee local Stack pointer
Save area • Linkage information: • Control link: previous value of frame pointer • Static link: address of stack frame of lexical parent • Return address: in caller • Other saved registers. • Compiler emits prologue code to save frame pointer, increment stack pointer, save registers. • Stack (sp) := fp; -- save frame pointer after actuals • fp := sp; -- new frame starts here
Functions with variable number of parameters printf (“this is %d a format %d string”, x, y); • within body of printf, need to locate as many actuals as place-holders in the format string. • Solution: place parameters on stack in reverse order. Actuals at positive offset from FP, locals at negative offset from FP. actual n actual n-1 … actual 1 (format string) return address
Objects of dynamic size declare x : string (1..N); -- N global, non-constant y : string (1..N); begin... • where is the start of y in the activation record? • Solution 1: use indirection: activation record hold pointers. Simpler implementation, costly dynamic allocation., deallocation. • solution 2:: local indirection: activation record holds offset into stack. • Faster allocation/deallocation, complex implementation.
Run-time access to globals procedure outer is -- recursive global : integer; procedure inner is -- recursive local : integer; begin ... if global = local then -- how do we locate global? • Need run-time structure to locate activation record of statically enclosing scopes. Environment includes current activation record AND activation records of parent scopes.
Global linkage • Static chain: pointer to activation record of statically enclosing scope • Display:: array of pointers to activation records • Neither works for function values (higher-order functions) • functional languages allocate activation records on heap • may not work for pointers to functions • simpler if there is no nesting (C, C++, Java) • can check static legality in many cases (Ada)
Static Links • Activation record hold pointer to activation record of enclosing scope. Setup as part of call prologue. To enclosing scope To retrieve entity 3 frames out: 3 dereference operations outer outer outer inner inner inner inner
Display • Global array of pointers to current activation records outermost display ... outer To retrieve entity 3 frames out: one indexing operation outer outer inner inner inner inner
Subprogram parameters type proc is access procedure (X : Integer); procedure Perform (Helper : proc) is begin … proc (42); end; procedure Action (X : Integer) is … procedure Proxy is begin Perform (Action’Access); end; • Proxy can see (and call) Action, therefore environment of Action ( e.g static link) Is known to Proxy. Proxy transmits to Perform both a pointer to the code for Action, and the proper static link for it. -- ‘Access creates pair (ptr to Action , environment of Action) • simplest implementation if Env is pointer (static link) but can also be display: more efficient to retrieve non-local entities, less efficient for subprogram parameters, because display is array of variable size.
Functions as first-class values forceheap allocation of activation record • The environment of definition of the function must be preserved until the point of call: activation record cannot be reclaimed if it creates functions. • Functional languages require more complex run-time management. • Higher-order functions: functions that return (build) functions, are powerful but complex mechanisms. Imperative languages restrict their use. • A function that returns a pointer to a function is a higher-order function.
Higher-order functions • Both arguments and result can be (pointers to) subprograms: type Func is access function (x : integer) return integer; function compose (first, second : Func) return Func is begin function result (x : integer) return integer is begin return (second (first (x)); -- implicit dereference on call end; -- in C++ as well. begin return result ’access; -- but first and second won’t exist at the point end; -- of call, soillegal in Ada.
Restricting higher-order functions • C: no nested definitions, so environment is always global. • C++: ditto, except for nested classes. • Ada: static checks to reject possible dangling references • Modula: pointers to function illegal if function not declared at top-level. • LISP: special syntax to indicate capture of environment • ML, Haskell: no restriction: compose is a primitive
Returning composite values • Intermediate problem: functions that return values of non-static sizes: function conc3 (x, y, z : string) return string is begin return x & “:” & y & “:” & z; end; example : string := conc3 (this, that, theother); • best not to use heap, but still need indirection. • Simplest : forbid it (Pascal, C) or use heap automatically (Java) • More efficient: local allocate/free on special stack. • Historical (algol68): two stacks.
Storage management • Data local to functions: stack • Global data: static areas • Class information, static members • Packages • Fortran common blocks • Linker establishes array of pointers to static areas (TOC). • Dynamic data: heap
Garbage collection • Run-time system manages heap, maintains free list • Allocation by first-fit or best-fit (variants with buddy system, etc). • Garbage collector must be able to distinguish data that is live from unreachable data. • Garbage collector attaches unreachable data (garbage) to free list. • Garbage collector may compact data in use, to improve program locality
Marking live data • Data is live if it can be referenced from any active function • Garbage collector must have run-time information on data layout: • Pointer data in activation records • Pointer data in data structures • Marking is a graph traversal starting from roots: pointers in the stack. • User cannot have control over pointer manipulation: • Languages with garbage collection do not have explicit pointers.
Sweeping and compacting garbage • Linear pass over the heap: all unmarked data is unreachable, and can be chained onto the free list • For compaction, rewrite live data contiguously, so that free space is also contiguous • Additional pass to adjust pointers: need to compute destination address of each block, and modify all pointers into that block. Needs inverse graph: each block has a chain of references to itself. • After pointers are adjusted, each block is copied to its destination.