subroutines and control abstraction n.
Skip this Video
Loading SlideShow in 5 Seconds..
Subroutines and Control Abstraction PowerPoint Presentation
Download Presentation
Subroutines and Control Abstraction

Loading in 2 Seconds...

play fullscreen
1 / 44

Subroutines and Control Abstraction - PowerPoint PPT Presentation

  • Uploaded on

Subroutines and Control Abstraction. Control Abstraction. Abstraction associate a name N to a program part P name describes the purpose or function of P we can use N instead of P (implementation) Control abstraction P is a well-defined operation Data abstraction

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
Download Presentation

PowerPoint Slideshow about 'Subroutines and Control Abstraction' - torn

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
control abstraction
Control Abstraction
  • Abstraction
    • associate a name N to a program part P
    • name describes the purpose or function of P
    • we can use N instead of P (implementation)
  • Control abstraction
    • P is a well-defined operation
  • Data abstraction
    • P represents information (often with operations to access & modify that information)
  • Principal mechanism of control abstraction
    • subroutine performs some operation on behalf of a caller
    • caller waits for the subroutine to finish
    • subroutine may be parameterized
      • caller passes arguments (actual parameters)
        • influence the behavior of the subroutine
        • pass data to operate with
      • arguments are mapped to subroutine’s formal parameters
    • subroutine may return a value
      • functions & procedures
chapter contents
Chapter contents...
  • Review of the stack layout
  • Calling sequences
    • maintaining the stack
    • static chains & display to access nonlocals
    • subroutine inlining
    • closures
    • implementation examples
  • Parameter passing
    • mode determines
      • how arguments are passed and
      • how subroutine operations affect them
    • conformant array parameters, named & default parameters
    • variable number of arguments
    • function return mechanisms
chapter contents1
...Chapter contents
  • Generic subroutines and modules
  • Exception handling
    • mechanism to ‘pop out’ of a nested context without returning
    • recovery happens in the calling context
  • Coroutines
    • a control abstraction other than a subroutine
    • useful for iterators, simulation, server programs
review of stack layout
Review of stack layout
  • Stack frame / activation record
    • arguments, return values
    • bookkeeping information
      • return address
      • saved register values
    • local variables, temporaries
    • static part
    • variable-sized part
accessing stack data
Accessing stack data
  • Hardware support
    • stack pointer register SP: top of the stack
    • frame pointer register FP: address within the current frame
  • Objects of the frame are accessed
    • using FP and a static displacement (offset) or
    • using address & dope vector (which are in the static part)
    • no variable-sized objects  all objects have a static offset  one can use SP instead of FP (and save one register)
  • Variable-sized arguments?
    • method 1
      • store below current frame
      • use address/dope vector in argument area
    • method 2
      • pass just the address (to caller object) & dope vector
      • copy object to ‘normal’ variable-sized area when subroutine is entered
nested routines static scoping
Nested routines & static scoping
  • Pascal, Modula, Ada
  • Note: many voices against the need of these
    • development of object-oriented programming
    • C works just fine without them
  • Accessing non-local objects
    • maintain static chain in frames (next slide)
    • each stack frame contains a static link
      • reference to the frame of the last activation of the lexically enclosing subroutine
    • by analogy, saved value of FP = dynamic link
      • reference to the frame of the caller
      • used to reclaim stack data
      • may (or may not) be the same as the static link
  • Figure slide -1
  • Call from a lexically surrounding routine
    • C is called from B
    • we know that B must be active (and has a frame in the stack)
  • How else can C be called?
    • C gets visible only when control enters B
    •  C is visible only from B & D (and routines declared in C & D)
  •  whatever routine P calls C, it must have a frame in the stack
  • Static chains may (in theory) be long
    • accessing an object k levels out requires the dereferencing of k static links
    •  k+1 memory accesses
  • Display / display table
    • static chain embedded into an array
    • an entry for each lexical depth of the program
    • Display[j] = FP of the last activation of a routine declared at depth j
  • Using display
    • caller nested i levels deep
    • object nested k levels out of caller
    • take frame Display[i-k] & use (compile-time constant) offset
display or static chain
Display or static chain?
  • Most programs are only 2 or 3 levels deep
    • static chains are short
  • If a non-local object X is used often
    • address calculation (arithmetic expression) of the frame of X, say FX, appears often in the code

 common subexpression optimization automatically loads FX to some register

 dereferencing is done only once

  • Cost of maintaining display
    • slightly higher than maintaining static links
  • Closures
    • easy to represent with static links
    • whole display has to be copied (if used)
      • some optimizations are possible
  • compilers that use a display have a limit on the depth of nesting
calling sequences
Calling sequences...
  • Maintenance of the call stack
    • code immediately before & after a call
    • prologue: code at the beginning of a subroutine
    • epilogue: code at the end of a subroutine
    • all above = ‘calling sequence’
  • Tasks to do ‘on the way in’
    • pass parameters
    • save return address
    • update program counter
    • update stack pointer (to allocate space)
    • save registers (including the frame pointer)
      • only those that are important and

may be overwritten by the called routine (= callee)

    • update frame pointer (to point to the new frame)
    • initialize local data objects
calling sequences1
...Calling sequences
  • Tasks to do ‘on the way out’
    • pass return parameters & function values
    • finalize local objects
    • deallocate frame (restore SP)
    • restore other saved registers
    • restore program counter (PC)
  • Division of the labor
    • some tasks can be done only by the caller
      • passing parameters

in general, things that may be different for different calls

    • most can be done by either one
      • the more work in the callee the less space we need for the code
saving registers
Saving registers
  • Ideally, save only those that
    • are used by the caller and
    • are overwritten by the callee
    • hard to track in separate compilation
  • Simpler solution
    • caller saves all registers that are in use, or
    • callee saves all registers it will overwrite
  • Compromise
    • divide (data) registers into ‘caller-saves’ & ‘callee saves’
    • callee can assume there is nothing of interest in caller-saves
    • caller can assume no callee destroys callee-saves registers
    • compiler allocates
      • callee-saves registers for long-term data
      • caller-saves for temporary data
      •  caller-saves are seldom saved at all (caller knows that they contain junk)
maintaining static chain
Maintaining static chain
  • Caller’s responsibility
    • links depend on the lexical nesting depth of the caller
  • Standard approach
    • compute the static link of the callee
      • callee directly inside caller: own FP
      • callee is k levels outward: follow k static links
    • pass it as an extra parameter
  • Maintaining displays
    • callee at level j 
    • save Display[j] in the stack
    • replace Display[j] with callee’s FP
    • why does it work: page 433
  • Leaf routines
    • routines that make no subroutine calls
    • no need to update Display for these
implementing closures
Implementing closures
  • Display scheme breaks for closures
    • use 2 entry points for each subroutine
      • normal call
      • via closure call
        • save Display[1..j] into stack
        • replace those with ones stored in the closure
    • separate return code for closure calls
      • restore Display[1..j]
cost of maintenance
Cost of maintenance
  • Static chains
    • call: k >= 0 load instructions, 1 store
    • return: no extra operations
  • Display
    • 1 load & 1 store in prologue
    • 1 load & 1 store in epilogue
  • No work for leaf routines
case study c on mips
Case study: C on MIPS
  • Hardware support
    • ra: register containing return address
    • jal: (jump and link) sets ra
    • sp, fp
  • Notes
    • a simple language on a simple machine
    • all stack object sizes known 
      • separate fp is not strictly needed (sp suffices)
      • GNU gcc uses it anyway
        • uniformity (gcc is highly portable)
        • makes it possible to allocate space dynamically from the stack (alloca library function)
stack frame
Stack frame...
  • Example of a stack frame (slide +1)
  • Argument passing
    • assembled at the top of the frame (using sp)
      • build area is large enough to hold the largest argument list
      • no need to ‘push’ in the traditional sense (space is already allocated and sp does not change)
    • optimization
      • first 4 scalar arguments are passed in machine registers
      • space is reserved in stack for all arguments
      • register arguments are saved to stack if needed
        • e.g. we must pass a pointer to the argument
stack frame1
...Stack frame
  • Allocate temporary space from stack
    •  sp grows, fp stays
    • C: alloca library routine
    • fast to implement, automatic reclaiming
    • see slide +1
  • Languages with nested subroutines
    • not C
    • use some register to pass the static link (r2)
returning values
Returning values
  • Scalar values (and pointers)
    • use some register (r2, f0)
  • Structures
    • store to a given memory address
      • address is passed in a ‘hidden’ register parameter (r4)
    • possible cases
      • x = foo(...)  address of x is passed to foo
      • p(...,foo(...),...)
        • pass an address to the build area (argument list of p)
        • overwrites arguments of foo but they are not in use when returning from foo
      • x = foo(...).a + y  use temporary variables
gcc calling sequence
gcc calling sequence...
  • Caller
    • save “caller-save” registers in temporary variables
      • only those whose value is still needed after the call
    • put (up to 4) scalar arguments into registers
    • put remaining arguments (if any) into the build area
    • perform jal instruction (sets ra & jumps)
  • Callee (prologue)
    • subtract frame size from sp (stack grows downwards)
      • note: argument list belongs to the caller’s frame
    • save fp, ra (if not a leaf routine)
    • save callee-save registers
      • only those whose values may change before returning
gcc calling sequence1
...gcc calling sequence
  • Callee (epilogue)
    • place return value (r2, f0, memory address)
    • copy fp into sp (deallocate alloca space)
    • restore saved registers (using sp)
    • add frame size to sp (deallocate frame)
    • jump to ra
  • Caller (at return)
    • move return values to wherever needed
    • caller-save registers are restored lazily
      • when values are needed for the first time
optimizations debugging
Optimizations & debugging
  • Optimizations
    • many parts of the calling sequence can be omitted
      • e.g. no caller-saves
    • many leaf routines do not use the stack at all
      • everything happens inside registers
  • Debugger support
    • compiler places information in the symbol table
      • starting & ending address of routines
      • size of the frame
      • whether sp or fp is used for object access
      • which register holds return address
      • which registers are saved (callee-saves)
inline expansion
Inline expansion
  • Alternative to stack-based calling
  • Expand routine body at the place of the call
    • avoids various overheads
      • space allocation
      • branching to and from subroutine
      • saving and restoring registers (not always)
    • code improvement possible ‘over routine boundaries’
  • Language design
    • compiler chooses which calls to expand
    • C++: keyword inline
      • only a suggestion to the compiler
    • Ada: compilation pragmas
      • pragma inline
inline expansion macros
Inline expansion & macros
  • In-line expansion
    • just an implementation technique
    • semantic of the program is not touched
  • Macros
    • side-effects in arguments are evaluated at each argument occurrence

#define MAX(a,b) ((a) > (b) ? (a) : (b))

MAX (x++, y++)

    • only expressions can be used to ‘return’ values
      •  no loops etc can be used in macros
inline expansion discussion
Inline expansion: discussion
  • Code speed increases
    •  programmers can use good programming style and still get good performance
      • e.g. class member functions to access/update instance data
    •  inline expansion may be a necessity for o-o languages
      • at least if we want programmers to write good programs
  • Code size increases
  • Recursive routines?
    • expand once
      • filter out the first special cases
      • nested calls are compiled ‘normally’
    • example case: hash table lookup
      • most chains in a table are only one element long
      • nested call is often avoided
parameter passing
Parameter passing
  • Use of subroutine parameters
    • control behavior
    • provide data to operate on
    • parameters make subroutines more abstract
  • Formal parameters
    • names in the declaration of a subroutine
  • Actual parameters, arguments
    • variables & expressions in subroutine calls
section contents
Section contents
  • Parameter-passing modes
    • values, references & closures
  • Additional mechanisms
    • conformant array parameters
    • missing & default parameters
    • named parameters
    • variable-length argument lists
  • Returning values (from functions)
subroutine call notation
Subroutine call notation
  • Prefix
    • most commonly used: p(a,b,c)
    • Lisp: (p a b c)
  • Infix
    • functions specified to be ‘operators’

infixr 8 tothe; (* exponentiation *)

fun x tothe 0 = 1.0

| x tothe n = x * (x tothe (n-1)); (* assume n>= 0 *)

  • Mixfix
    • Smalltalk: arguments & function name interleaved
  • Note on uniformity
    • Lisp & Smalltalk functions are like ‘standard’ control structures
    •  more natural to introduce ‘own’ control abstractions

if a > b then max := a else max := b; (* Pascal *)

(if (> a b) (setf max a) (setf max b)) ; Lisp

(a > b) ifTrue: [max <_a] ifFalse: [max<- b]. ”Smalltalk”

parameter modes
Parameter modes
  • Semantic rules governing parameter passing
    • determine relationship between the actual & formal parameters
    • single set of rules that apply to all parameters
      • C, Fortran, ML, Lisp
    • two or more sets of rules
      • each corresponding to some mode
      • Pascal, Modulas, Ada
    • heavily influenced by implementation issues
call by value call by reference
Call by value & call by reference
  • Example: global x, call p(x)
    • what is passed to p?
    • call by value: a copy of x
      • x & the copy are independent of each other
    • call by reference: the address of x
      • formal parameter is an alias for x
      • most languages require that ‘x’ must have an l-value
        • Fortran 90 makes one if it doesn’t
value model languages
Value model languages
  • Pascal
    • by value: default mode
    • by reference
      • use keyword VAR in the formal parameter list
  • C
    • all parameters are passed by value
      • exception: array is passed as a pointer

aliases must be created explicitly

      • declare a formal pointer parameter

use address operator on the actual parameter

void swap (int *a, int *b) {int t = *a, *a = *b, *b = t;}


swap (&v1, &v2);

  • Fortran
    • all variables are passed by reference
reference model languages
Reference model languages
  • Actual parameter is already a reference
    •  sensible to define only a single passing mode
      • Clu: call by sharing
    • actual & formal parameter refer to the same object
  • Implementation
    • as an address  pass the address
    • as a value (immutable objects)  copy value
    • Java: primitive values are copied, class objects shared
function returns
Function returns
  • restrictions on the types of objects that can be returned
    • Algol 60, Fortran: a scalar value
    • Pascal, early Modula-2: scalar or pointer
    • Algol 68, Ada, C, some Pascal: composite type values
    • Modula-3, Ada 95: a subroutine, implemented as a closure
    • Lisp, ML: closure
function return syntax
Function return syntax
  • Lisp, ML, Algol 68
    • no distinction between statements and expressions
    • value of the function is the value of its body
  • Algol 60, Fortran, Pascal

function := expression

    • problems with nested declarations
  • more recent languages

return expression

    • immediate termination of the subroutine
    • if the function still has something to do, then place the return value into a temporary variable

rtn := expression


return rtn

function return
...Function return
  • Fortran

function name := ...


  • Ada example
    • return expression
  • SR example
    • result of a function has its own name