1 Subroutines and Control Abstraction Aaron Bloomfield CS 415 Fall 2005.

Post on 30-Dec-2015

214 views 0 download

Tags:

transcript

1

Subroutines and Control Abstraction

Aaron Bloomfield

CS 415

Fall 2005

2

Definitions

• Function: subroutine that returns a value

• Procedure: subroutine that does not return a value

3

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

4

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

5

Review of Stack Layout (cont’d)

Static chain

- Each stack frame contains a reference to the lexically surrounding subroutine

6

Review of Stack Layout (cont’d)

Display

- used to reduce memory accesses to an object k levels out

7

Calling Sequences

• Calling sequence: code executed by the caller immediately before and after a subroutine call

• Prologue

• Epilogue

8

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

9

Case Study 1: C on the MIPS (example of RISC)

10

Case Study 2: Pascal on the 680x0 (example of CISC)

11

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)

12

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.

13

In-line Expansion versus Macros

• in-line expansion– Semantically

preferable– Disadvantages?

• macros– Semantic problems– Syntactic problems

14

Parameter Passing

Parameter Modes

Special-Purpose Parameters

Function Returns

15

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 of abstraction

16

More Basics

• Formal Parameters - parameter name in the subroutine declaration

• Actual Parameters – values passed to a subroutine in a particular call

17

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

18

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

19

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

20

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

21

Value vs. Reference

• Pass by Value– Called routine cannot modify the Actual

Parameter

• Pass by Reference– Called routine can modify Actual Parameter

22

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…

23

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

24

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

25

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

26

Review: references to functions

• When are scope rules applied?

– When the function is called?• Shallow binding

– When the reference is created?• Deep binding

27

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; } return max_score;}

main() { max_score = 50; int[] scores = ... print highest_score (scores, scale_score);}

function is called

reference is created

28

Deep Binding

• Generally the default in lexically (statically) scoped languages

• Dynamically scoped languages tend to use shallow binding

29

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

30

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]);

}

31

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

32

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

33

Generic Subroutines and Modules

Generic Subroutines

Generic Modules

34

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

35

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

36

Exception Handling

37

Exceptions

• Exceptions are an unexpected or unusual condition that arises during program execution.

• Most common are various sorts of run-time errors (ex. encountering the end of a file before reading a requested value)

38

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

39

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.

40

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 re-raise the exception to propagate back up.

41

Defining Exceptions

• Ada

declare empty_queue : exception;

• Modula-3

EXCEPTION empty_queue;

• C++ and Javaclass empty_queue{};

42

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.}

43

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.

44

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.

45

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 of Code Block

Address of Corresponding Handler

46

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.

47

Coroutines

48

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.

49

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.

50

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.