Warning: this optimization is difficult to do it perfectly, and therefore, expect a big bonus.
In a first and conservative extension, the compiler considers that all
the functions (but the builtins!) need a static link. This is correct,
but inefficient: for instance, the traditional fact
function will
spend almost as much time handling the static link, than its real
argument.
Some functions need a static link, but don't need to save it on the stack. For instance, in the following example:
let var foo := 1 function foo () : int = foo in foo () end
the function foo
does need a static link to access the variable
foo
, but does not need to store its static link on the stack.
It is suggested to address these problems in the following order:
$ tc -E fact.tig /* == Escapes. == */ let function fact (/* escaping sl *//* escaping */ n : int) : int = if (n = 0) then 1 else (n * fact ( (n - 1))) in fact (10) end $ tc -eE fact.tig /* == Escapes. == */ let function fact (n : int) : int = if (n = 0) then 1 else (n * fact ( (n - 1))) in fact (10) end
call
and progFrag
prologues.
$ tc -eE escaping-sl.tig /* == Escapes. == */ let var toto := 1 function outer (/* escaping sl */) : int = let function inner (/* sl */) : int = toto in inner () end in outer () end
Watch out, it is not trivial to find the minimum. What do you think
about the static link of the function sister
below?
let var toto := 1 function outer () : int = let function inner () : int = toto in inner () end function sister () : int = outer () in sister () end