Re: exceptions & dataflow

"Sergey Solyanik" <sergey@solyanik.com>
10 Feb 1998 01:35:08 -0500

          From comp.compilers

Related articles
exceptions & dataflow djames@cs.utah.edu (David James) (1998-02-03)
Re: exceptions & dataflow acha@play.cs.ucsb.edu (Anurag Acharya) (1998-02-07)
Re: exceptions & dataflow sergey@solyanik.com (Sergey Solyanik) (1998-02-07)
Re: exceptions & dataflow jason@cygnus.com (Jason Merrill) (1998-02-08)
Re: exceptions & dataflow dlmoore@ix.netcom.com (David L Moore) (1998-02-08)
Re: exceptions & dataflow dlmoore@ix.netcom.com (David L Moore) (1998-02-09)
Re: exceptions & dataflow sergey@solyanik.com (Sergey Solyanik) (1998-02-10)
Re: exceptions & dataflow jason@cygnus.com (Jason Merrill) (1998-02-10)
Re: exceptions & dataflow mcdirmid@beaver.cs.washington.edu (1998-02-10)
Re: exceptions & dataflow jeremy@softway.com.au (1998-02-10)
Re: exceptions & dataflow jason@cygnus.com (Jason Merrill) (1998-02-12)
Re: exceptions & dataflow fjh@hydra.cs.mu.oz.au (Fergus Henderson) (1998-02-12)
Re: exceptions & dataflow chase@world.std.com (David Chase) (1998-02-12)
[4 later articles]
| List of all articles for this month |
From: "Sergey Solyanik" <sergey@solyanik.com>
Newsgroups: comp.compilers
Date: 10 Feb 1998 01:35:08 -0500
Organization: Bentley Systems, Inc
References: 98-02-025 98-02-027 98-02-034
Keywords: analysis, optimize

Jason Merrill <jason@cygnus.com> wrote>
> I'm not sure what you're saying. I'm not very familiar with Java, but
> finally blocks seem analogous to C++ implicit destructors in terms of
> when they get run; the finally block is run on exit from the try block
> by any means, and in C++ implicit destructors are run when a variable
> goes out of scope by any means. I will call the two constructs
> 'cleanups'.


Yes, but finally also has full access to all other local variables. In
C++ you, as far as I understand, can get away with list of destructors
to call.


> Our approach has been to treat cleanups as additional exception
> regions. We duplicate the code for cleanups, so you have one copy
> where flow continues into the rest of the program, and one that is
> followed by a rethrow into an outer exception context. This seems to
> work well, and there is no need to spill anything if register values
> are preserved by your throw mechanism; flow handles this just fine.


By the way, how do you do it? The whole dataflow approach without
spilling everyplace indeed makes sence if preserved across call
registers are somehow restored by throw.


It happens to be just so in (ours or Java's) bytecode, but I have
failed to consider "normal" CPUs.


One way would be to save registers preserved by callee _ALWAYS_ in a
known place on the stack frame, but this is inefficient and also will
inhibit user from utilizing code compiled by different
compilers. (E. g. if your function is small and does not use EDI, why
save it - and many (or most) compilers won't).


> In the case of finally, if you check the exception types inline, your
> flow graph would have an edge from the case where none of the catch
> blocks matched to the second copy of the finally block. If you check
> the exception types in the throw mechanism, you would have edges from
> each of the calls in the try block, just like your edges to the catch
> blocks.


It is another way around:


CATCH1:
CALL #CLEANUP
...
CATCH2:
CALL #CLEANUP
...
CATCH*:
CALL #CLEANUP
RETHROW


There is no need of duplication in this approach.


> If you can jump out of the exception region with return or break, you
> can make a third or fourth copy. If you can jump out with goto (does
> Java have goto?), this gets a bit more complicated, as you need to
> decide where you're going to put the code for the cleanup. We put it
> at the goto site, and have to do some fiddling with exception regions
> to avoid having an exception thrown from the cleanup jump to the
> cleanup again.


We just insert calls to finally right before control breaks out of
exception. This is why dataflow analysis gets complicated and
duplication may, indeed, be a good idea. Again, unlike destructors,
nothing prevents user from putting code of any complexity in there (in
case of destructors, you just do not inline the big ones, but in case
of finallies, local vars must be accessible).


> We haven't decided yet what to do about this case. We'd like to find
> a way to retain some basic block optimizations...


In C++ you can treat at least references as pointer accesses that
cannot generate exceptions. General pointer dereference,
unfortunately, always can...


Regards --


Sergey Solyanik
Software Developer,
Bentley Systems, Inc


Sergey.Solyanik@bentley.com




--


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.