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.