Subroutines and Control Abstraction Aaron Bloomfield CS 415

advertisement
Subroutines and Control
Abstraction
Aaron Bloomfield
CS 415
Fall 2005
1
Definitions
• Function: subroutine that returns a value
• Procedure: subroutine that does not
return a value
2
Review of Stack Layout
• Storage consumed by parameters and
local variables can be allocated on a stack
• Activation record contains arguments
and/or return values, bookkeeping info,
local variables, and/or temporaries
• On return, stack frame is popped from
stack
3
Review of Stack Layout (cont’d)
• Stack pointer: contains address of the first
unused location at the top of the stack
• Frame pointer: contains address within
frame
• Displacement addressing
• Objects with unknown size placed in
variable-size area at top of frame
4
Review of Stack Layout (cont’d)
Static chain
- Each stack frame contains a reference to
the lexically surrounding subroutine
5
Review of Stack Layout (cont’d)
Display
- used to reduce memory accesses to an
object k levels out
6
Calling Sequences
• Calling sequence: code executed by the
caller immediately before and after a
subroutine call
• Prologue
• Epilogue
7
Calling Sequences (cont’d)
• Tasks on the way in (prologue)
– Passing parameters, saving return address,
changing program counter, changing stack
pointer, saving registers, changing frame
pointer
• Tasks on the way out (epilogue)
– Passing
return
parameters,
executing
finalization code, deallocating stack frame,
restoring saved registers and pc
8
Case Study 1: C on the MIPS
(example of RISC)
9
Case Study 2: Pascal on the 680x0
(example of CISC)
10
In-Line Expansion
• Allows certain subroutines to be expanded
in-line at the point of call
• Avoids
several
overheads
(space
allocation, branch delays, maintaining
static chain or display, saving and
restoring registers)
11
Implementations of In-line
Expansion
• C++ uses keyword inline:
inline int max( … ) { … }
• Ada:
pragma inline (function_name);
• Pragmas make suggestions to the
compiler. Compiler can ignore suggestion.
12
In-line Expansion versus Macros
• in-line expansion
– Semantically
preferable
– Disadvantages?
• macros
– Semantic problems
– Syntactic problems
13
Parameter Passing
Parameter Modes
Special-Purpose Parameters
Function Returns
14
Parameter Passing Basics
• Parameters - arguments that control
certain aspects of a subroutine’s behavior
or specify the data on which they are to
operate
• Global Variables are other alternative
• Parameters increase the level
abstraction
of
15
More Basics
• Formal Parameters parameter name in
the
subroutine
declaration
• Actual Parameters –
values passed to a
subroutine
in
a
particular call
16
Parameter Modes
• Some languages define a single set of
rules which apply to all parameters
– C, Fortran, Lisp
• Some languages provide two or more sets
of rules, which apply to different parameter
modes
– Algol, Pascal, Ada, Modula
– We will discuss Ada Parameter Modes in
more detail
17
Call by Value
•
•
•
•
For P(X), two options are possible: Call by
Value and Call by Reference
Call by Value - provides P with a copy of X’s
value
Actual parameter is assigned to the
corresponding
formal
parameter
when
subroutine is called, and the two are
independent from then on
Like creating a local or temporary variable
18
Call by Reference
• Call by Reference – provide P with the
address of X
• The formal parameter refers to the same
object as the actual parameter, so that
changes made by one can be seen by the
other
19
Language Specific Variations
• Pascal: Call by Value is the default, the
keyword VAR denotes Call by Reference
• Fortran: all parameters passed by
Reference
• Smalltalk, Lisp: Actual Parameter is
already a reference to the object
• C: always passed by Value
20
Value vs. Reference
• Pass by Value
– Called routine cannot modify the Actual
Parameter
• Pass by Reference
– Called routine can modify Actual Parameter
21
Call by name
• Pretty much only in Algol
• Re-evaluates the actual parameter on every use
– For actual parameters that are simple variables, it’s
the same as call by reference
– For actual parameters that are expressions, the
expression is re-evaluated on each access
• No other language ever used call by name…
22
Safety and Efficiency
• Without language support, working with
large objects that are not to be modified
can be tricky
– Call by Value:
– Call by Reference:
• Examples of Language Support
– Modula: READONLY parameter mode
– C/C++: const keyword
23
Ada Parameter Modes
Three parameter passing modes
• In
– Passes information from the caller to the callee, can
read but not write
– Call by Value
• Out
– Passes information from the callee to the caller, can
write but not read
– Call by Result (formal parameter is copied to actual
parameter when subroutine exits)
• Inout - passes information both directions
24
C++ Parameter Modes
C passes pointers as addresses, must be
explicitly dereferenced when used
C++ has notion of references:
• Parameter passing:
void swap (int &a, int &b)
• Variable References: int &j = i;
• Function Returns: for objects that don’t
support copy operations, i.e. file buffers
25
Review: references to functions
• When are scope rules applied?
– When the function is called?
• Shallow binding
– When the reference is created?
• Deep binding
26
int max_score;
float scale_score (int raw_score) {
return (float) raw_score / (float) max_score;
}
float highest_score (int[] scores, function_ptr scaling_function) {
float max_score = 0;
foreach score in scores {
float percent = scaling_function (score);
if ( percent > max_score )
max_score = percent;
function is called
}
return max_score;
}
main() {
reference is created
max_score = 50;
int[] scores = ...
print highest_score (scores, scale_score);
}
27
Deep Binding
• Generally the default in lexically (statically)
scoped languages
• Dynamically scoped languages tend to
use shallow binding
28
Closures
• Implementation of Deep Binding for a
Subroutine
– Create an explicit representation of the
current referencing environment and its
bindings
– Bundle this representation with a reference to
the subroutine
– This bundle is called a Closure
29
Closures as Parameters
• Closures: a reference
to a subroutine and its
referencing
environment
• Closures can be
passed as a
parameter
• Pascal, C, C++,
Modula, Scheme
void apply_to_A (int (*f) (int),
int A[], int A_size)
{
int i;
for (i = 0; i < A_size; i++)
A[i] = f (A[i]);
}
30
Special-Purpose Parameters
• Named Parameters - parameters that are not
positional, also called keyword parameters. An
Ada example:
funcB (argA => 21, argB => 35);
funcB (argB => 35, argA => 21);
• Some languages allow subroutines with a
variable number of arguments: C, Lisp, etc.
int printf (char *format, …) {…
• Standard Macros in function body to access
extra variables
31
Function Returns
• Some languages restrict Return types
– Algol 60, Fortran: scalars only
– Pascal, Modula: scalars or pointers only
– Most imperative languages are flexible
• Return statements specify a value and
also cause the immediate termination of
the subroutine
32
Generic Subroutines and
Modules
Generic Subroutines
Generic Modules
33
Generic Subroutines
• Large Programs often use the same data
structures for different object types
• Characteristics of the queue data structure
independent of the characteristics of the
items in the queue
• Polymorphic subroutines
– Argument types are incompletely specified
– Can cause slower compilation
– Sacrifice compile-time type checking
34
Generic Modules
• Similar subroutines are created from a
single piece of source code
• Ada, Clu, Modula-3
• C++ templates
• Similar to macros, but are actually
integrated into the rest of the language
• Follow scope, naming, and type rules
35
Exception Handling
36
Exceptions
• Exceptions are an unexpected or unusual
condition that arises during program
execution.
• Most common are various sorts of runtime errors (ex. encountering the end of a
file before reading a requested value)
37
Handling Exceptions
• Exception handling was pioneered by PL/I
• Utilized an executable statement of the following
form:
ON condition
statement
• Handler is nested inside and is not executed on
the ON statement but is remembered for future
reference.
• Executes exception when exception condition is
encountered
38
Handling Exceptions
• Recent languages provide exception-handling
facilities where handlers are lexically bound to
blocks of code.
• General rule is if an exception isn’t handled in
the current subroutine, then the subroutine
returns and exception is raised at the point of
call.
• Keeps propagating up dynamic chain until
exception is handled.
• If not handled a predefined outermost handler is
invoked which will terminate the program.
39
3 Main Handler Uses
• 1) Perform some operation that allows the
program to recover from the exception and
continue executing.
• 2)If recovery isn’t possible, handler can print
helpful message before termination
• 3)When exception occurs in block of code but
can’t be handled locally, it is important to declare
local handler to clean up resources and then reraise the exception to propagate back up.
40
Defining Exceptions
• Ada
declare empty_queue : exception;
• Modula-3
EXCEPTION empty_queue;
• C++ and Java
class empty_queue{};
41
Exception Propagation
try{
...
//protected block of code
...
}catch(end_of_file) {
...
}catch(io_error e) {
//handler for any io_error other than end_of_file
...
}catch(…) {
//handler for any exception not previously named
//… is a valid token in the case in C++, doesn’t
//mean code has been left out.
}
42
Implementing Exceptions
• Can be made as a linked list stack of
handlers.
• When control enters a protected block,
handler for that block is added to head of
list.
• Propagation down the dynamic chain is
done by a handler in the subroutine that
performs the work of the subroutine’s
epilogue code and the reraises the
exception.
43
Problems With This
Implementation
• Incurs run-time overhead in the common
case
• Every protected block and every
subroutine begins with code to push a
handler onto the handler list, and ends
with code to pop it off the list.
44
A Better Implementation
• Since blocks of code in machines can
translate to continuous blocks of machine
instructions, a table can be generated at
compile
time
that
captures
the
correspondence between blocks and
handlers
Starting Address Address of
of Code Block
Corresponding
Handler
45
Implementing Exceptions
• Table is sorted by the first field of the table
• When an exception occurs the system
performs a search of the table to find the
handler for the current block.
• If handler re-raises the exception, the
process repeats.
46
Coroutines
47
Coroutines
• Coroutines are execution contexts that
exist concurrently, but execute one at a
time, and transfer control to each other
explicitly, by name.
• They can implement iterators and threads.
48
Stack Allocation
• Since they are concurrent they can’t share a single stack because
subroutine calls and returns aren’t LIFO
• Instead the run-time system uses a cactus stack to allow sharing.
49
Transfer
• To go from one coroutine to another the
run-time system must change the PC,
stack, and register contents.
This is
handled in the transfer operation.
50
Download