1 subroutines and control abstraction. 2 control abstraction abstraction abstraction associate a...
TRANSCRIPT
22
Control AbstractionControl Abstraction
AbstractionAbstraction associate a name N to a program part Passociate a name N to a program part P name describes the name describes the purposepurpose or function of P or function of P we can use N instead of P (implementation)we can use N instead of P (implementation)
Control abstractionControl abstraction P is a well-defined operationP is a well-defined operation
Data abstractionData abstraction P represents information (often with operations P represents information (often with operations
to access & modify that information)to access & modify that information)
33
SubroutinesSubroutines
Principal mechanism of control abstractionPrincipal mechanism of control abstraction subroutine performs some operation on behalf subroutine performs some operation on behalf
of a of a callercaller caller waits for the subroutine to finishcaller waits for the subroutine to finish subroutine may be subroutine may be parameterizedparameterized
caller passes caller passes argumentsarguments ( (actual parametersactual parameters)) influence the behavior of the subroutineinfluence the behavior of the subroutine pass data to operate withpass data to operate with
arguments are mapped to subroutine’s arguments are mapped to subroutine’s formal formal parametersparameters
subroutine may return a valuesubroutine may return a value functions & proceduresfunctions & procedures
44
Chapter contents...Chapter contents...
Review of the stack layoutReview of the stack layout Calling sequencesCalling sequences
maintaining the stackmaintaining the stack static chains & display to access nonlocalsstatic chains & display to access nonlocals subroutine inliningsubroutine inlining closuresclosures implementation examplesimplementation examples
Parameter passingParameter passing modemode determines determines
how arguments are passed and how arguments are passed and how subroutine operations affect themhow subroutine operations affect them
conformant array parameters, named & default parametersconformant array parameters, named & default parameters variable number of argumentsvariable number of arguments function return mechanismsfunction return mechanisms
55
...Chapter contents...Chapter contents
Generic subroutines and modulesGeneric subroutines and modules Exception handlingException handling
mechanism to ‘pop out’ of a nested context mechanism to ‘pop out’ of a nested context without returningwithout returning
recovery happens in the calling contextrecovery happens in the calling context CoroutinesCoroutines
a control abstraction a control abstraction otherother than a subroutine than a subroutine useful for iterators, simulation, server useful for iterators, simulation, server
programsprograms
66
Review of stack layoutReview of stack layout
Stack frame / activation recordStack frame / activation record arguments, return valuesarguments, return values bookkeeping informationbookkeeping information
return addressreturn address saved register valuessaved register values
local variables, temporarieslocal variables, temporaries static partstatic part variable-sized partvariable-sized part
99
Accessing stack dataAccessing stack data
Hardware supportHardware support stack pointerstack pointer register SP: top of the stack register SP: top of the stack frame pointerframe pointer register FP: address within the current frame register FP: address within the current frame
Objects of the frame are accessed Objects of the frame are accessed using FP and a static displacement (offset) orusing FP and a static displacement (offset) or using address & dope vector (which are in the static part) using address & dope vector (which are in the static part) no variable-sized objects no variable-sized objects all objects have a static offset all objects have a static offset
one can use SP instead of FP (and save one register)one can use SP instead of FP (and save one register) Variable-sized Variable-sized arguments?arguments?
method 1method 1 store store below below current framecurrent frame use address/dope vector in argument areause address/dope vector in argument area
method 2method 2 pass just the address (to caller object) & dope vector pass just the address (to caller object) & dope vector copy object to ‘normal’ variable-sized area when subroutine is copy object to ‘normal’ variable-sized area when subroutine is
enteredentered
1010
Nested routines & static Nested routines & static scopingscoping
Pascal, Modula, AdaPascal, Modula, Ada Note: many voices against the need of theseNote: many voices against the need of these
development of object-oriented programmingdevelopment of object-oriented programming C works just fine without themC works just fine without them
Accessing non-local objectsAccessing non-local objects maintain maintain static chain static chain in frames (next slide)in frames (next slide) each stack frame contains a each stack frame contains a static linkstatic link
reference to the frame of the last activation of the lexically reference to the frame of the last activation of the lexically enclosing subroutineenclosing subroutine
by analogy, saved value of FP = by analogy, saved value of FP = dynamic linkdynamic link reference to the frame of the callerreference to the frame of the caller used to reclaim stack dataused to reclaim stack data may (or may not) be the same as the static linkmay (or may not) be the same as the static link
1212
ExampleExample
Figure slide -1Figure slide -1 Call from a lexically surrounding routineCall from a lexically surrounding routine
C is called from BC is called from B we know that B must be active (and has a we know that B must be active (and has a
frame in the stack)frame in the stack) How else can C be called?How else can C be called?
C gets visible only when control enters BC gets visible only when control enters B C is visible only from B & D (and routines C is visible only from B & D (and routines
declared in C & D)declared in C & D) whatever routine P calls C, it must have whatever routine P calls C, it must have
a frame in the stacka frame in the stack
1313
DisplayDisplay
Static chains may (in theory) be longStatic chains may (in theory) be long accessing an object k levels out requires the accessing an object k levels out requires the
dereferencing of k static linksdereferencing of k static links k+1 memory accessesk+1 memory accesses
Display / display tableDisplay / display table static chain embedded into an arraystatic chain embedded into an array an entry for each lexical depth of the programan entry for each lexical depth of the program Display[j] = FP of the last activation of a routine declared Display[j] = FP of the last activation of a routine declared
at depth jat depth j Using displayUsing display
caller nested i levels deepcaller nested i levels deep object nested k levels out of callerobject nested k levels out of caller take frame Display[i-k] & use (compile-time constant) take frame Display[i-k] & use (compile-time constant)
offsetoffset
1515
Display or static chain?Display or static chain?
Most programs are only 2 or 3 levels deepMost programs are only 2 or 3 levels deep static chains are shortstatic chains are short
If a non-local object X is used oftenIf a non-local object X is used often address calculation (arithmetic expression) of the frame of X, say FX, address calculation (arithmetic expression) of the frame of X, say FX,
appears often in the codeappears often in the code common subexpression optimization automatically loads FX to some common subexpression optimization automatically loads FX to some registerregister dereferencing is done only oncedereferencing is done only once
Cost of maintaining displayCost of maintaining display slightly higher than maintaining static linksslightly higher than maintaining static links
ClosuresClosures easy to represent with static linkseasy to represent with static links whole display has to be copied (if used)whole display has to be copied (if used)
some optimizations are possiblesome optimizations are possible compilers that use a display have a limit on the depth of nestingcompilers that use a display have a limit on the depth of nesting
1616
Calling sequences...Calling sequences...
Maintenance of the call stackMaintenance of the call stack code immediately before & after a callcode immediately before & after a call prologueprologue: code at the beginning of a subroutine: code at the beginning of a subroutine epilogueepilogue: code at the end of a subroutine: code at the end of a subroutine all above = ‘calling sequence’all above = ‘calling sequence’
Tasks to do ‘on the way in’Tasks to do ‘on the way in’ pass parameterspass parameters save return addresssave return address update program counterupdate program counter update stack pointer (to allocate space)update stack pointer (to allocate space) save registers (including the frame pointer)save registers (including the frame pointer)
only those that are important andonly those that are important andmay be overwritten by the called routine (= callee)may be overwritten by the called routine (= callee)
update frame pointer (to point to the new frame)update frame pointer (to point to the new frame) initialize local data objectsinitialize local data objects
1717
...Calling sequences...Calling sequences
Tasks to do ‘on the way out’Tasks to do ‘on the way out’ pass return parameters & function valuespass return parameters & function values finalize local objectsfinalize local objects deallocate frame (restore SP)deallocate frame (restore SP) restore other saved registersrestore other saved registers restore program counter (PC)restore program counter (PC)
Division of the laborDivision of the labor some tasks can be done only by the callersome tasks can be done only by the caller
passing parameterspassing parametersin general, things that may be different for different callsin general, things that may be different for different calls
most can be done by either onemost can be done by either one the more work in the callee the less space we need for the the more work in the callee the less space we need for the
codecode
1818
Saving registersSaving registers
Ideally, save only those thatIdeally, save only those that are used by the caller andare used by the caller and are overwritten by the calleeare overwritten by the callee hard to track in separate compilationhard to track in separate compilation
Simpler solutionSimpler solution caller saves all registers that are in use, orcaller saves all registers that are in use, or callee saves all registers it will overwritecallee saves all registers it will overwrite
CompromiseCompromise divide (data) registers into ‘caller-saves’ & ‘callee saves’divide (data) registers into ‘caller-saves’ & ‘callee saves’ callee can assume there is nothing of interest in caller-savescallee can assume there is nothing of interest in caller-saves caller can assume no callee destroys callee-saves registerscaller can assume no callee destroys callee-saves registers compiler allocatescompiler allocates
callee-saves registers for long-term datacallee-saves registers for long-term data caller-saves for temporary datacaller-saves for temporary data caller-saves are seldom saved at all (caller knows that they contain junk)caller-saves are seldom saved at all (caller knows that they contain junk)
1919
Maintaining static chainMaintaining static chain
Caller’s responsibilityCaller’s responsibility links depend on the lexical nesting depth of the callerlinks depend on the lexical nesting depth of the caller
Standard approachStandard approach compute the static link of the calleecompute the static link of the callee
callee directly inside caller: own FPcallee directly inside caller: own FP callee is k levels outward: follow k static linkscallee is k levels outward: follow k static links
pass it as an extra parameterpass it as an extra parameter Maintaining displaysMaintaining displays
callee at level j callee at level j save Display[j] in the stacksave Display[j] in the stack replace Display[j] with callee’s FPreplace Display[j] with callee’s FP why does it work: page 433why does it work: page 433
Leaf routinesLeaf routines routines that make no subroutine callsroutines that make no subroutine calls no need to update Display for theseno need to update Display for these
2020
Implementing closuresImplementing closures
Display scheme breaks for closuresDisplay scheme breaks for closures use 2 entry points for each subroutineuse 2 entry points for each subroutine
normal callnormal call via closure callvia closure call
save Display[1..j] into stacksave Display[1..j] into stack replace those with ones stored in the closurereplace those with ones stored in the closure
separate return code for closure callsseparate return code for closure calls restore Display[1..j]restore Display[1..j]
2121
Cost of maintenanceCost of maintenance
Static chainsStatic chains call: k >= 0 load instructions, 1 storecall: k >= 0 load instructions, 1 store return: no extra operationsreturn: no extra operations
DisplayDisplay 1 load & 1 store in prologue1 load & 1 store in prologue 1 load & 1 store in epilogue1 load & 1 store in epilogue
No work for leaf routinesNo work for leaf routines
2222
Case study: C on MIPSCase study: C on MIPS
Hardware supportHardware support ra: register containing return addressra: register containing return address jal: (jump and link) sets rajal: (jump and link) sets ra sp, fpsp, fp
NotesNotes a simple language on a simple machinea simple language on a simple machine all stack object sizes known all stack object sizes known
separate fp is not strictly needed (sp suffices)separate fp is not strictly needed (sp suffices) GNU gcc uses it anywayGNU gcc uses it anyway
uniformity (gcc is highly portable)uniformity (gcc is highly portable) makes it possible to allocate space dynamically from makes it possible to allocate space dynamically from
the stack (alloca library function)the stack (alloca library function)
2323
Stack frame...Stack frame...
Example of a stack frame Example of a stack frame (slide +1)(slide +1)
Argument passingArgument passing assembled at the top of the frame (using sp)assembled at the top of the frame (using sp)
build area is large enough to hold the largest argument build area is large enough to hold the largest argument listlist
no need to ‘push’ in the traditional sense (space is no need to ‘push’ in the traditional sense (space is already allocated and sp does not change)already allocated and sp does not change)
optimizationoptimization first 4 scalar arguments are passed in machine registersfirst 4 scalar arguments are passed in machine registers spacespace is reserved in stack for is reserved in stack for allall arguments arguments register arguments are saved to stack if neededregister arguments are saved to stack if needed
e.g. we must pass a pointer to the argumente.g. we must pass a pointer to the argument
2525
...Stack frame...Stack frame
Allocate temporary space from stackAllocate temporary space from stack sp grows, fp stayssp grows, fp stays C: alloca library routineC: alloca library routine fast to implement, automatic reclaimingfast to implement, automatic reclaiming see slide +1see slide +1
Languages with nested subroutinesLanguages with nested subroutines not Cnot C use some register to pass the static link use some register to pass the static link
(r2)(r2)
2727
Returning valuesReturning values
Scalar values (and pointers)Scalar values (and pointers) use some register (r2, f0)use some register (r2, f0)
StructuresStructures store to a given memory address store to a given memory address
address is passed in a ‘hidden’ register parameter address is passed in a ‘hidden’ register parameter (r4)(r4)
possible casespossible cases x = foo(...) x = foo(...) address of x is passed to foo address of x is passed to foo p(...,foo(...),...) p(...,foo(...),...)
pass an address to the build area (argument list of p)pass an address to the build area (argument list of p) overwrites arguments of foo but they are not in use overwrites arguments of foo but they are not in use
when returning from foowhen returning from foo x = foo(...).a + y x = foo(...).a + y use temporary variables use temporary variables
2828
gcc calling sequence...gcc calling sequence...
CallerCaller save “caller-save” registers in temporary variablessave “caller-save” registers in temporary variables
only those whose value is still needed after the callonly those whose value is still needed after the call put (up to 4) scalar arguments into registersput (up to 4) scalar arguments into registers put remaining arguments (if any) into the build areaput remaining arguments (if any) into the build area perform jal instruction (sets ra & jumps)perform jal instruction (sets ra & jumps)
Callee (prologue)Callee (prologue) subtract frame size from sp (stack grows downwards)subtract frame size from sp (stack grows downwards)
note: argument list belongs to the caller’s framenote: argument list belongs to the caller’s frame save fp, ra (if not a leaf routine) save fp, ra (if not a leaf routine) save callee-save registers save callee-save registers
only those whose values may change before returningonly those whose values may change before returning
2929
...gcc calling sequence...gcc calling sequence
Callee (epilogue)Callee (epilogue) place return value (r2, f0, memory address)place return value (r2, f0, memory address) copy fp into sp (deallocate alloca space)copy fp into sp (deallocate alloca space) restore saved registers (using sp)restore saved registers (using sp) add frame size to sp (deallocate frame)add frame size to sp (deallocate frame) jump to rajump to ra
Caller (at return)Caller (at return) move return values to wherever neededmove return values to wherever needed caller-save registers are restored lazily caller-save registers are restored lazily
when values are needed for the first timewhen values are needed for the first time
3030
Optimizations & debuggingOptimizations & debugging
OptimizationsOptimizations many parts of the calling sequence can be many parts of the calling sequence can be
omittedomitted e.g. no caller-savese.g. no caller-saves
many leaf routines do not use the stack at allmany leaf routines do not use the stack at all everything happens inside registerseverything happens inside registers
Debugger supportDebugger support compiler places information in the symbol tablecompiler places information in the symbol table
starting & ending address of routinesstarting & ending address of routines size of the framesize of the frame whether sp or fp is used for object accesswhether sp or fp is used for object access which register holds return addresswhich register holds return address which registers are saved (callee-saves)which registers are saved (callee-saves)
3131
Inline expansionInline expansion
Alternative to stack-based callingAlternative to stack-based calling Expand routine body at the place of the callExpand routine body at the place of the call
avoids various overheadsavoids various overheads space allocationspace allocation branching to and from subroutinebranching to and from subroutine saving and restoring registers (not always)saving and restoring registers (not always)
code improvement possible ‘over routine boundaries’code improvement possible ‘over routine boundaries’ Language designLanguage design
compiler chooses which calls to expandcompiler chooses which calls to expand C++: keyword C++: keyword inlineinline
only a suggestion to the compileronly a suggestion to the compiler Ada: compilation pragmasAda: compilation pragmas
pragma inlinepragma inline
3232
Inline expansion & macrosInline expansion & macros
In-line expansion In-line expansion just an implementation techniquejust an implementation technique semantic of the program is not touchedsemantic of the program is not touched
MacrosMacros side-effects in arguments are evaluated at side-effects in arguments are evaluated at
each argument occurrenceeach argument occurrence#define MAX(a,b) ((a) > (b) ? (a) : (b))#define MAX(a,b) ((a) > (b) ? (a) : (b))
MAX (x++, y++)MAX (x++, y++)
only expressions can be used to ‘return’ valuesonly expressions can be used to ‘return’ values no loops etc can be used in macrosno loops etc can be used in macros
3333
Inline expansion: discussionInline expansion: discussion
Code speed increasesCode speed increases programmers can use good programming style and still get programmers can use good programming style and still get
good performancegood performance e.g. class member functions to access/update instance datae.g. class member functions to access/update instance data
inline expansion may be a inline expansion may be a necessitynecessity for o-o languages for o-o languages at least if we want programmers to write good programsat least if we want programmers to write good programs
Code size increasesCode size increases Recursive routines?Recursive routines?
expand onceexpand once filter out the first special casesfilter out the first special cases nested calls are compiled ‘normally’nested calls are compiled ‘normally’
example case: hash table lookupexample case: hash table lookup most chains in a table are only one element longmost chains in a table are only one element long nested call is often avoidednested call is often avoided
3535
Parameter passingParameter passing
Use of subroutine parametersUse of subroutine parameters control behaviorcontrol behavior provide data to operate onprovide data to operate on parameters make subroutines more parameters make subroutines more
abstractabstract Formal parametersFormal parameters
names in the declaration of a subroutinenames in the declaration of a subroutine Actual parameters, argumentsActual parameters, arguments
variables & expressions in subroutine callsvariables & expressions in subroutine calls
3636
Section contentsSection contents
Parameter-passing Parameter-passing modesmodes values, references & closuresvalues, references & closures
Additional mechanismsAdditional mechanisms conformant array parametersconformant array parameters missing & default parametersmissing & default parameters named parametersnamed parameters variable-length argument listsvariable-length argument lists
Returning values (from functions)Returning values (from functions)
3737
Subroutine call notationSubroutine call notation
PrefixPrefix most commonly used: p(a,b,c)most commonly used: p(a,b,c) Lisp: (p a b c)Lisp: (p a b c)
InfixInfix functions specified to be ‘operators’functions specified to be ‘operators’
infixr 8 tothe; (* exponentiation *)infixr 8 tothe; (* exponentiation *)fun x tothe 0 = 1.0fun x tothe 0 = 1.0
| x tothe n = x * (x tothe (n-1)); (* assume n>= 0 *)| x tothe n = x * (x tothe (n-1)); (* assume n>= 0 *) MixfixMixfix
Smalltalk: arguments & function name interleavedSmalltalk: arguments & function name interleaved Note on uniformityNote on uniformity
Lisp & Smalltalk functions are like ‘standard’ control structures Lisp & Smalltalk functions are like ‘standard’ control structures more natural to introduce ‘own’ control abstractionsmore natural to introduce ‘own’ control abstractions
if a > b then max := a else max := b;if a > b then max := a else max := b; (* Pascal *)(* Pascal *)(if (> a b) (setf max a) (setf max b))(if (> a b) (setf max a) (setf max b)) ; Lisp; Lisp(a > b) ifTrue: [max <_a] ifFalse: [max<- b].(a > b) ifTrue: [max <_a] ifFalse: [max<- b]. ”Smalltalk””Smalltalk”
3838
Parameter modesParameter modes
Semantic rules governing parameter Semantic rules governing parameter passingpassing determine relationship between the actual & determine relationship between the actual &
formal parametersformal parameters single set of rules that apply to all parameterssingle set of rules that apply to all parameters
C, Fortran, ML, LispC, Fortran, ML, Lisp two or more sets of rulestwo or more sets of rules
each corresponding to some each corresponding to some modemode Pascal, Modulas, AdaPascal, Modulas, Ada
heavily influenced by implementation issuesheavily influenced by implementation issues
3939
Call by value & call by Call by value & call by referencereference
Example: global x, call p(x)Example: global x, call p(x) what is passed to p?what is passed to p? call by value: a copy of xcall by value: a copy of x
x & the copy are independent of each otherx & the copy are independent of each other call by reference: the address of xcall by reference: the address of x
formal parameter is an alias for xformal parameter is an alias for x most languages require that ‘x’ must have most languages require that ‘x’ must have
an l-valuean l-value Fortran 90 makes one if it doesn’tFortran 90 makes one if it doesn’t
4040
Value model languagesValue model languages
PascalPascal by value: default modeby value: default mode by referenceby reference
use keyword VAR in the formal parameter listuse keyword VAR in the formal parameter list CC
all parameters are passed by valueall parameters are passed by value exception: array is passed as a pointerexception: array is passed as a pointer
aliases must be created explicitlyaliases must be created explicitly declare a formal pointer parameterdeclare a formal pointer parameter
use address operator on the actual parameteruse address operator on the actual parametervoid swap (int *a, int *b) {int t = *a, *a = *b, *b = t;}void swap (int *a, int *b) {int t = *a, *a = *b, *b = t;}......swap (&v1, &v2);swap (&v1, &v2);
FortranFortran all variables are passed by referenceall variables are passed by reference
4141
Reference model languagesReference model languages
Actual parameter is already a referenceActual parameter is already a reference sensible to define only a single passing modesensible to define only a single passing mode
Clu: Clu: call by sharingcall by sharing actual & formal parameter refer to the same actual & formal parameter refer to the same
objectobject ImplementationImplementation
as an address as an address pass the address pass the address as a value (immutable objects) as a value (immutable objects) copy value copy value Java: primitive values are copied, class objects Java: primitive values are copied, class objects
sharedshared
4242
Function returnsFunction returns
restrictions on the types of objects restrictions on the types of objects that can be returnedthat can be returned Algol 60, Fortran: a scalar valueAlgol 60, Fortran: a scalar value Pascal, early Modula-2: scalar or pointerPascal, early Modula-2: scalar or pointer Algol 68, Ada, C, some Pascal: Algol 68, Ada, C, some Pascal:
composite type valuescomposite type values Modula-3, Ada 95: a subroutine, Modula-3, Ada 95: a subroutine,
implemented as a closureimplemented as a closure Lisp, ML: closureLisp, ML: closure
4343
Function return syntaxFunction return syntax
Lisp, ML, Algol 68Lisp, ML, Algol 68 no distinction between statements and expressionsno distinction between statements and expressions value of the function is the value of its bodyvalue of the function is the value of its body
Algol 60, Fortran, PascalAlgol 60, Fortran, Pascalfunction := function := expressionexpression
problems with nested declarationsproblems with nested declarations more recent languagesmore recent languages
return return expressionexpression immediate termination of the subroutineimmediate termination of the subroutine if the function still has something to do, then place the if the function still has something to do, then place the
return value into a temporary variablereturn value into a temporary variablertn := rtn := expressionexpression......return rtnreturn rtn