1 / 50

Subroutines and Control Abstraction

Subroutines and Control Abstraction. Aaron Bloomfield CS 415 Fall 2005. Definitions. Function : subroutine that returns a value Procedure : subroutine that does not return a value. Review of Stack Layout. Storage consumed by parameters and local variables can be allocated on a stack

kiana
Télécharger la présentation

Subroutines and Control Abstraction

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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation 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 Semantically preferable Disadvantages? macros Semantic problems Syntactic problems In-line Expansion versus Macros • increasing code size • Generally not an option for recursive subroutines

  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 Pascal – to prevent from assigning an out of range value

  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 • +safe • - Copying may be time consuming • Pass by Value • Called routine cannot modify the Actual Parameter • Pass by Reference • Called routine can modify Actual Parameter • +Only have to pass an address, efficient • -Requires an extra level of indirection

  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 time consuming potential bugs in code 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: 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]); } Closures as Parameters

  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 Java class 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

  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.

More Related