This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: extending libgcc's exception delivery path


> 
> > 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]