This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: extending libgcc's exception delivery path
- To: mrs at windriver dot com (Mike Stump)
- Subject: Re: extending libgcc's exception delivery path
- From: Godmar Back <gback at cs dot utah dot edu>
- Date: Tue, 7 Dec 1999 14:18:29 -0700 (MST)
- Cc: gback at cs dot utah dot edu, gcc at gcc dot gnu dot org, tim at transvirtual dot com
>
> > From: Godmar Back <gback@cs.utah.edu>
> > Date: Mon, 6 Dec 1999 17:19:31 -0700 (MST)
>
> > When I started the integration work, I found one or two sources with
> > information about DWARF2 on the web [...] Does anybody have more
> > pointers?
>
> There is a reference from http://egcs.cygnus.com/readings.html to
> ftp://sgigate.sgi.com/pub/dwarf/ on our web site. Not sure how
> complete that is for you. I've never read it myself.
>
Thanks. I looked at it, and I don't think it contains any x86
specific information. It does, however, contain the source for
a producer/consumer library. It seems to have been released by
SGI under a BSD-like license in May 1996.
Since you've never read it yourself, I assume you didn't use that
library in gcc. (Any reason why not? Did someone investigate its use
when gcc's implementation was done?)
>
> > - check whether a monitor associated with that frame must be unlocked
> > and if so do it. I don't actually know how I would do that with dwarf.
>
> I generally do this type of work using the native EH constructs in the
> source language (or specifically, the midlevel end that the frontend
> uses to generate code). Why go any lower, I don't see any advantage?
I believe it's certainly faster than wrapping the function in
try/finally->rethrow, as gcj currently does. I would imagine that
it's also better in general to have simpler trees in the code generation
phase. It's certainly simpler to implement (one `if' statement in the
exception handling code).
I think there's of course a trade-off between flexibility and prescribing
a certain way of doing things. I honestly don't know all the trade-offs
involved in that particular design decision, but I don't think the issue
is clearcut at this point. Hence, my gut feeling would be to allow for
multiple ways of doing it.
>
> > - check whether the frame is inside some special assembly code for which
> > I don't have exception handling information and if so skip it.
>
> :-) Oh, the simplicity of that statement. Sorry, this generally is
> really hard to do.
Maybe I didn't express well what I wanted to say.
Let me show you some code. Suppose I have x86 assembly code like this:
trampoline_1:
call trampoline_2 # returns address in %eax
jmp *%eax
A frame that has return address "trampoline_1+5" needs to be skipped
if "trampoline_2" or a function called by it causes an exception.
I can do this easily by overriding the frame_state_for function.
With Dwarf2, my understanding is that I need a FDE entry for that.
>
> > The DWARF2 information, from what I can tell, is interpreted for every
> > exception thrown, currently twice per stackframe. Bypassing DWARF does
> > avoid repeatedly interpreting the same information over and over.
>
> After you benchmark it, and after you devise a way to make it faster,
> and after you get the maintainers to accept it... we can talk. I
> have done multiple high performance EH implementations for gcc before,
> think 218 from throw to catch block, total. I fall over laughing at
> implementations that featured 30000+ instructions. Our current
> incantation is fairly high, but it does have one feature, it is
> accepted by the maintainers and is in the compiler.
>
I am a bit confused as to what you're trying to say or imply here.
I'm not criticizing the current implementation of eh handling in gcj,
primarily because I don't have anything better to offer.
However, preliminary benchmark results indicate that, compared to current
products such as IBM's JDK, high-performance may not be the right term.
Try running JVMSpec's _228_jack or the UCSD java benchmarks. For the
latter, it takes GCJ 40 seconds to perform a million throws while IBM's
JDK takes less than 3 seconds for the same number. A bogus test, I know.
In any event, it really doesn't bother me.
I don't have the time, inclination, skills or experience to
redesign gcc's eh implementation. My primary interest is finding a way
for me to interoperate with gcc's EH mechanism. It is my believe that
such a way might be beneficial to other people besides me, which I think
is why you're even participating in this discussion.
>
> New radical thought, screw dwarf. Just use the native EH table and
> put in registrations for all frame unwinding you need to do. The
> format? Oh, too trivial to even explain:
>
> ; code outside try block
> .LEHB3:
> code inside try clock
> .LEHE3:
> code outside try block
>
> .L3:
> ; handler for exceptions thrown in the try block above
>
>
> __EXCEPTION_TABLE__:
> ; ...
> .LRTH3:
> .long .LEHB3
> .long .LEHE3
> .long .L3
> .long 0
>
>
> You can then `generate' code as you see fit, based upon whatever
> philosophy you want to use. It really doesn't get any simpler or
> basic than this. If you want a generic handler for frames, you just
> put that handler in instead of the L3. All of this is trival to
> generate during run time, and I don't think that hard to figure out,
> maintain, implement, and get working. You then don't need any hooks
> into the throw stuff, as you get control via this interface. Also,
> this interface should not change that much (though the 4 longs per
> entry is new to me, it had always only been three before).
>
> Does this work for you?
>
I'm not sure whether this addresses the problem.
Let me ask a question:
In your scheme, how would I communicate callee-saved registers to a
precompiled caller? Suppose I have a precompiled caller invoke a
translated method, which saves some callee-saved register upon which
the catch clause in the precompiled handler relies.
For example:
precompiled_f:
...
mov value, %edi
call *just_in_time_compiled_fp
...
EH:
...
uses %edi
just_in_time_compiled_f:
...
push %edi
...
call precompiled_f_2
...
precompiled_f_2:
...
call __throw
Could you outline how I'd communicate the saved value of %edi to
precompiled_f when precompiled_f_2 throws an exception caught by "EH"?
- Godmar