10.1.
1 Static Chains
The most common way to implement static scoping in languages that
support nested subprograms is static chaining.
A new pointer, called Static Link, is added to the Activation Record.
Static Link is sometimes called static scope pointer.
Static Link is used to access to nonlocal variables.
Static Chain is the chain of static Links.
When a reference is made to a nonlocal variable, the Activation Record
instance is in the static chain.
How to find the ARI that contains the nonlocal variable?
Compiler can determine the distance of the ARI on the static chain.
Static_depth of a subprogram is the depth of nesting.
Static_depth(main) = 0.
Static depth(A) = 1 + static_depth(A’s static parent).
Nesting_depth (chain_offset) of a variable:
static_depth(ARI of reference) – static_depth(ARI of delaration)
Then, address of a variable is represented by a pair
(chain_offset, local_offset),
Implementing Subprograms 2
function main(){
var x = 5;
function bigsub() {
var a, b, c;
function sub1 {
var a, d;
a = b + c;
...
} // end of sub1
function sub2(x) {
var b, e;
function sub3() {
var c, e;
...
sub1();
...
e = b + a;
} // end of sub3
...
sub3();
...
a = d + e;
} // end of sub2 Sequence of calls:
...
sub2(7);
main calls bigsub
... bigsub calls sub2
} // end of bigsub
... sub2 calls sub3
bigsub(); sub3 calls sub1
...
} // end of main
Implementing Subprograms 3
Activation Records:
main: Local variable(x)
bigsub: Local var (c)
Local var (b)
Local var (a)
Local offset
Dynamic Link
Static Link local_offset(a) = 3
Return Address
sub1: Local var (d)
Local var (a)
Dynamic Link
Static Link
Return Address
sub2: Local var (e)
Local var (b)
Parameter (x)
Dynamic Link
Static Link
Return Address
sub3: Local var (e)
Local var (c)
Dynamic Link
Static Link
Return Address
Implementing Subprograms 4
function main(){
var x = 5;
function bigsub() { Chain_offset
var a, b, c;
function sub1() { local_offset
var a, d;
a = b + c; ---------(0,3) = (1,4) + (1,5)
...
} // end of sub1
function sub2(x) {
var b, e;
function sub3() {
var c, e;
...
sub1();
...
e = b + a; -------(0,4) = (1,4) + (2,3)
} // end of sub3 ...
sub3();
...
a = d + e; ---------(1,3) = d: ??? Error
} // end of sub2
...
sub2(7);
...
} // end of bigsub
...
bigsub();
...
} // end of main
Contents of the Runtime Stack:
Implementing Subprograms 5
Implementing Subprograms 6
Implementing Subprograms 7
Implementing Subprograms 8
How to maintain the static links?
Where should a Static Link point to when a new ARI is created?
It should point to the most recent ARI of the static parent.
How to find the most recent ARI of the static parent?
For example, when sub1() is called from sub3(), the ARI of sub1() should
point to the ARI of bigsub(), which is the static parent of sub1().
Solution: Compiler computes: nesting_depth(caller, called): as
Static_depth(caller) – static_depth (unit that declared called).
It the example above:
Caller: sub3
Callee: sub1
Static parent of Callee: bigsub
nesting_depth(sub3, sub1):
= Static_depth(sub3) - static_depth(unit that declared sub1)
= Static_depth(sub3) - static_depth(bigsub)
=3–1
= 2.
So, SL of the ARI of sub1 should point to the 2nd ARI in the static chain.