- Functions and procedures.
- Arguments and parameters (or formal parameters or
- Parameter passing
- Standard parameter passing methods.
- Pass by value.
- Each parm receives a copy of the arg.
- Parms are just variables initialized to the arg.
- Pass by reference.
- C++ reference parameters and Pascal VAR parameters.
- Parameter is a pointer to the argument.
- Operations always performed on the target.
- Pass by value-result
- Copy argument values to parameters at call, copy back at exit.
- Historically used by FORTRAN.
- Not a requirement.
- Used on early FORTRAN because pointers were expensive on the IBM
architecture it ran on.
- Pass by result.
- Pass by name.
- Historical: Used by Algol; abandoned since.
- Parameters stand exactly for arguments; like macro substitution.
- Algol Example
- Jensen's Device
- Mutable reference.
- This is not a standard term.
- Form of pass-by-reference.
- Parameter is a reference.
- Operations using the parameter effect the argument object.
- Assignments to the parameter change what it refers to.
- Used in C, C++, Java and many OO languages.
- Different languages use different passing
methods based on type, and parameter declaration.
- FORTRAN: By reference (presently) or
by value-result in the past.
- Algol Example: By name, unless declared
By value, unless declared VAR to make them by reference.
- C: By value, except arrays are passed by mutable reference (a C
- C++: C, plus & declarations pass by reference.
- Java: simple data pass by value, objects by mutable reference (a Java
- Ruby: mutable reference.
- Ada specifies the use, not the means: declare in, out,
or in out.
- Implementer can choose the appropriate means.
- Ada Example
- Parameter Passing
- Activation records.
- When a function is running, its status is recorded in an activation
- Parameter storage.
- Local variables.
- Temporary storage needed by the compiler.
- Assembler-level bookkeeping.
- The PC value to jump to upon function return.
- Other saved CPU registers.
- Static pointer (or context pointer).
- Points to the activation record needed to find non-local references.
- The chain of static pointers gives the full referencing
- Omitted when
- The language has dynamic scope, which nothing does anymore.
- Methods may not be nested, so the only non-local
references are global. This is the case for C and C++.
- Dynamic pointer.
- Points to the activation record of the caller.
- Needed to implement returns, exceptions, and (if any) dynamic scope.
- May be omitted if the value can be computed from the storage
- Each function has a statically-allocated block of memory which
is used as an activation record while the function is running.
- Used on some early languages (notably FORTRAN), but now considered
- Will not support recursion, since a function can only have at most
one activation record at a time.
- Organized as a stack.
- When a function is called, a new activation record is pushed on
the stack. Popped after return.
- Stacks may be linked, but are usually a linear block of memory
with a top pointer.
- Usually considerable hardware support for this model.
- Typical function call:
- Push the arguments onto the stack.
- Push the hardware return address (PC) into the frame and
jump to the function address.
- Push the local and temp variables onto the stack.
- Establish the static and dynamic pointers (see below).
- Frame may be in different places on different calls.
- Variables may not take the same location each time.
- Multiple copies of some variables may exist.
- Important for recursive functions.
- Finding a variable.
- The compiler does not know the l-value of a variable, but
knows its offset from the start of its AV.
- It knows how to find the start of the AV at run time.
- To find an l-value, the compiler generates “find frame, add
- For local references, this is just "stack pointer + offset".
- On most CPUs, the stack pointer is in a register, and these variables
can be fetched or stored in one instruction.
- Finding a non-local variable.
- In a language like C, there is only one non-local scope (the global
one). Offset from that instead of the stack pointer.
- If there are multiple scopes
- The static link in each AV points to the AV of the
- The compiler can compute the difference in scope depth between
reference and declaration.
- To find a non-local l-value, produce a translation
“follow the local pointer n times to give the correct
frame, then offset by the constant.”
- Establishing the static pointer when fa calls fb.
- From fa, the sequence of scopes searched to find a reference
can be given
Sn, Sn−1, Sn−2, …, S0,
where Sn is the scope defined by the body of fa, from which
fb is called.
- The activation record for fa is An, starting the
static chain of activation records
An, An−1, An−2, …, A0. These frames hold
the variables in each of the scopes.
- For fa to call fb, fb must visible, so it must appear in one of the
the scopes on that list. Say it appears in
Si, n ≤ i ≤ 0.
- Si is the scope that contains fb, but its local scope
(the scope of fb's body) is a different one, which we call
Sfb. So fb's chain should be
Afb, Ai, Ai−1, …, A0.
- Since subscripts are nesting depths, i − n
is just the difference in nesting depth between the call (within
fa) and the called function, fb. To find Ai,
follow the static chain from Afb
i − n times to reach
Ai. This difference may be zero, in which case
Ai is Afb.
- The static link of Afb should point to this Ai.
This creates the correct search chain,
Afb, Ai, Ai−1, …, A0.
- Languages which need a static link include Pascal, Ada and
Java (sort of).
- Pascal example
- Java example
- Functions don't nest, only classes.
- Non-local references are to enclosing class data.
- Links are between classes, and nesting levels are of classes
- Calling methods.
x.f(a,b,c) becomes roughly
class::f(x,a,b,c), where the first arg is just the this pointer.