val _ = () and exception optimization in MLton

Stephen Weeks MLton@sourcelight.com
Fri, 11 Aug 2000 16:30:43 -0700 (PDT)


> I'm  confused.   Wasn't  this the whole point of the compile-time part of the
> handler-stack?  (`This' being to not bother manipulating the handler stack in
> memory unless you called something.)

No.  The point of that was to only store the top of the compile-time part of the 
handler-stack in the current frame.
 
> I  still  don't  see why the current code doesn't cause more push-pops of the
> handler stack.  If I have a loop which is called inside  a  handle,  and  the
> loop  is  inlined, but in the loop it calls a procedure which is NOT inlined,
> then won't the new code push on the handler stack just before  the  call  and
> pop  after?   I.e.,  take  the  example  I sent you, and assume that outer IS
> inlined by inner is NOT inlined.  Then  the  old  code  would  do  1  handler
> push/pop  while  the new code will do 1000 push/pops, right?  I'm not arguing
> that the handler stack gets deeper, just that it fribulates more.
> 
> Am I still missing something?

No.  You are correct.  My earlier statement (about a constant factor) was wrong.
Here is a program that did one push in the old scheme and does 1000 in the new
scheme.

fun inner n =
   if n = ~1
      then raise Fail "z"
   else if n = 0
      then 13
   else 1 + inner (n - 1)

fun outer n =
   if n = 0
      then inner n
   else (inner n; outer (n - 1))

val _ = if 13 = (outer 1000 handle _ => 14)
	   then ()
	else raise Fail "bug"


So my previous optimization was too aggressive.  I could imagine some kind of
local flow analysis to try to improve stuff, but that sounds too messy.  Here is 
my new proposal.  The optimization will remove a handler push/pop if there are
no nontail calls in the scope of the handler, but will not otherwise move the
push/pop.