COP 3402 meeting -*- Outline -*- * Supporting Subroutines Q: What is a subroutine? It's a rule, abstract algorithm It's code that can be parameterized and used over and over - so it can be used to avoid repeating code In C it's a function, in Java/C# a method, ... It's an abstraction of an expression (computes a value) or a command (changes the program's state) in a way that depends on its parameters It's a key modularity feature in programming - clients can call it, - implementation may change code as long as it does what it should ** feature design to support subroutines The goal is to explain the features of an ISA that are needed to: 1. make writing subroutines easier, and 2. have them execute faster ------------------------------------------ GOALS FOR SUBROUTINES subroutine = function or procedure (abstraction of expressions or commands) Want: ------------------------------------------ ... - independent development - information hiding (decisions are local and independent) - maximal reuse (caller need not know details of decisions) - efficient execution ------------------------------------------ WHAT A SUBROUTINE CALL DOES What are the steps in a subroutine call like: x = f(E1,E2) where E1 and E2 are expressions? ------------------------------------------ This is with "call by value", which is used in C and in all OO languages and thus most modern programming languages. ... - caller evaluates argument expressions E1,E2 to get argument values - pass the argument values to the subroutine - callee does computation - pass the result, if any, back - caller continues right after the call Q: What happens in the machine to pass arguments? they (their values in call by value) are stored somewhere where the callee can find them ------------------------------------------ SUBROUTINE CALLS Call done by "CALL" or CSI instruction CALL addr means GPR[$ra] <- PC PC <- addr RTN means PC <- GPR[$ra] ------------------------------------------ Notes: - only the PC is saved in the RA register, nothing else is saved, not even the RA register! - on return, no registers are restored, only the PC is set from the RA register. Q: Who should save the registers and restore them? Need to decide on this "calling convention" ------------------------------------------ CALLING CONVENTION Agreement between all callers and callees Callee never changes the GP register Caller saves all other registers needed after the call Caller restores those registers, if any, upon return ------------------------------------------ Q: What complications arise for calls? - any registers, except for GP, might need to be saved & restored - in a recursion, registers are shared among routine activations - each subroutine activation needs its own stack frame, which has storage for locals so will change $sp and $fp Registers $ra, $sp, $fp and $s0-$s7 are preserved (saved by callee if need be, and restored when routine returns) The rest are not preserved by callee, so if the caller cares, then caller must save them and restore them after return ------------------------------------------ IT'S A CONVENTION / AGREEMENT Saving and restoring not enforced ------------------------------------------ ... by hardware - but it's useful to have everyone know what to do Why? Allows modularity/plug compatability ------------------------------------------ VM FEATURES TO SUPPORT SUBROUTINES ------------------------------------------ ... (starting with fundamental decisions in the ISA) - call and return instructions - must save the return address (PC) somewhere (in SSM it's saved in reg. 7 = RA) - arguments, and - result(s) - support for recursive subroutines ==> different calls (activations) need different space ==> may coexist at runtime - help to manage local storage for subroutines - formal parameter(s) - local variables (helps subroutine independence and reuse) - support for static scoping want to understand subroutine where it is written (names refer to surrounding declarations in text not to dynamically recent declarations) - way to return long-lived data - heap/global storage + more modern features (optional): + exception handling (instructions for throwing exceptions, which will unwind stack looking for handler) + passing and returning subroutines as values (heap allocation of ARs, closures) (doesn't need new capabilities from VM?) + objects and inheritance (heap allocation, virtual function tables/call instructions as in JVM) + support for multi-threading (multiple runtime stacks and thread switching, coroutines? locking/atomicity?)