[Gc] workaround for C++ exceptions problem

skaller skaller at users.sourceforge.net
Wed Jan 25 21:11:15 PST 2006


On Wed, 2006-01-25 at 22:57 -0500, Filip Pizlo wrote:
> On Jan 25, 2006, at 10:01 PM, skaller wrote:
> 
> > On Wed, 2006-01-25 at 16:20 -0500, Filip Pizlo wrote:
> > []
> >
> > The point of what I'm saying is that whoever tries to modify
> > the GC/C++runtime to work with C++ exceptions in g++, must find out
> > what happens to 'the' exception when another one is legally raised,
> > and, in what way 'the' exception is restored when the current
> > one is no longer required.
> 
> Sure.  Overriding __cxa_allocate_exception() gives us this for free.   
> Agreed?

I believe this is likely, yes. 
I don't *know* this for sure of course.

> If you look at my proposed GC_THROW() routine, then you also know.   
> Here it is again:
> 
> template< typename T >
> void GC_THROW(const T &exn) {
>     try {
>        throw exn;
>     } catch (const T &exn) {
>        void *ptr=&exn;
>        // ptr is the location of the exception slot
>        throw;
>     }
> }

I don't see how this shows how the stack is maintained.
This does show how to find the top exception on the stack.

Note that your technique has the advantage that there
is no need to know how the stack is maintained ..
provided your assumptions are correct :)

Oh .. BTW .. there is a BUG in your code: it isn't
const correct, you cannot store a T const* into
a void*. You need to cast away the const for this
to be conforming. (I think the rule is stupid
and tried to convince Stroustrupp he didn't know
what he was doing ..:)

> >
> > Are the exceptions pushed onto the machine stack?
> > Or are they chained together in a linked list?
> 
> Linked list, at least in the code I'm looking at.

Right. Possible reason is that it is much easier to
maintain the two stacks (machine stack, exception stack)
separately. 

> > Both implementations are viable. In both cases
> > the GC MIGHT be able to keep track of everything
> > just knowing the top slot, assuming it is in a fixed
> > place (which is stupid since it isn't thread safe unless
> > that place is in TLS)
> 
> I tried to determine from the C++ spec if there are some constraints  
> here.  Couldn't figure it out.

I'm not surprised :) C++ doesn't standardise dynamic loading
or thread handling. Both have to work right together with
exceptions.

> My guess is that the linked list approach is so much more efficient  
> that nobody is going to do it any other way.

The machine stack is probably faster due to cache coherence
issues BUT it is harder to organise, and really, who cares
about blinding speed whilst stack unwinding? 

> > Hans proposal is simpler: to mark the region containing
> > the pointer to the object as a root, and allocate
> > the exception objects as non-roots.
> 
> Hmmm.  I didn't understand Hans' proposal that way.  

I probably misunderstood it.

> I thought the  
> point was to make a copy of the exception so that you know what  
> pointers it has.  Or is this saying the same thing?

I don't see how it is possible to copy the exception,
except at the point it is thrown?

Also minor problem .. if the object contains pointers
into itself .. a bitwise copy will not preserve that.

If the object has virtual bases such pointers always
exist or can be constructed, even if the user didn't create them.
If they're offsets, you'll get a different result to full
pointers .. the pointer will point to the real exception.

This is messy .. :)

[Hummm .. and Felix GC has a way to move objects .. didn't
think about those virtual base pointers .. :[

> Perhaps it is because I don't see Hans' proposal this way, but I  
> think that with my hacks, Hans' proposal is less brittle than mine.   
> It doesn't require knowing what the ABI is, only that once an  
> exception is dropped into its slot, it stays there.  Of course, there  
> is actually no guarantee that this will be the case, but both  
> proposals are equally flawed in this regard.

I was assuming that Hans was assuming there was a single fixed
'slot' which I was trying to point out is not correct.

i would have guessed that there is indeed a single fixed 'top of
the exception stack' slot, and the remaining exceptions
are on a linked list.

In that case, the top slot will definitely change as
the stack is pushed and popped.

however this is too confusing to talk about.. the actual
code in front of you has the answer :)

> This is a non-stop issue for anyone using C++ in GCC.  

Yeah .. no wonder most language implementors target
assembler or C. Am I the only one targetting C++?

> But I've been  
> following the basic exception throwing machinery for quite some time,  
> and it always seems to have had the same basic elements.  So I feel  
> quite comfortable overriding __cxa_allocate_exception/ 
> __cxa_free_exception.

In that case can you shed some light on this (off list if you like):

> > -------
> > The current gcc implementation of catch sucks, it doesn't
> > work properly across DLL boundaries -- so the ABI may
> > well change again  :)

because it is a pretty serious pain for me.

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net



More information about the Gc mailing list