Projects

Jon Olson olson@mmsi.com
Fri May 5 15:19:00 GMT 2000


On 2000年5月05日, Jeff Sturm wrote:
>"Jonathan P. Olson" wrote:
>> The exception handling patches are definitely alot messier than write
>> barriers. Exceptions in gcc are currently quite broken on many architectures
>> and terribly inefficient on others. There are two different exception handling
>> strategies intermingled in the gcc code. Adding a third makes an enormous
>> spaghetti bowl and is contrary to the overall goal of eliminating compilation
>> options. I opted for just replacing the existing code, but I doubt if that's
>> politically acceptable for gcc in general since libraries are currently built
>> using the existing mechanism(s).
>>FYI I think one goal of GCC 3.0 is to eliminate the current sjlj
>expection
>handling mechanism. Apparently some maintainers feel it has caused more
>trouble than it was worth.
>
That's great news. Unfortunately, it must be replaced with something else.
The current alternative mechanism using range tables and stack unwinding
symbol tables is good where the binary lives on disk and the symbol tables
are free, but really bad for embedded programming when the symbol tables
must live in flash memory.
For embedded applications, I vote for a mechanism with near zero cost when
exceptions are not used, but slightly higher runtime cost when using
exceptions. The mechanism I used for `gcj' exception handling used the
following three functions:
void
__builtin_catch(ExceptionFrame *frame, ExceptionHandler *handlers)
{
}
void
__builtin_catch_pop()
{
}
volatile void
__builtin_throw(const void *e)
{
}
At the top of the try/catch block, I emit a call to __builtin_catch, passing
it an ExceptionFrame allocated within the stack frame of the current method
and a ExceptionHandler vector table emitted by the compiler. The ExceptionFrame
objects are singly linked backwards up the call stack. ExceptionHandler
entries contain a type field which for Java references the Java class entry and
a label entry point.
At the end of a try block, I emit a call to __builtin_catch_pop() which removes
the ExceptionHandler pushed by __builtin_catch().
Throwing an exception obviously invokes builtin_throw with the exception being
thrown. builtin_throw unwinds the exception stack, but note that each
ExceptionFrame contains the stack level so I don't need any particular support
for unwinding the hardware stack frame. On finding an ExceptionFrame which
matches the exception being thrown, __builtin_throw() pops its exception from
the stack and jumps to the exception entry point. Because the current
exception is already popped, there's no need to emit a __builtin_catch_pop()
at the end of the catch block(s) nor at the end of the Java finally block.
An advantage of this mechanism is that it integrates nicely with Java
synchronization. The `gcj' compiled code for Java synchronization generates
alot of try/catch blocks just to unlock monitors when exceptions get thrown. 
By making _Jv_MonitorEnter() push an exception onto the exception stack
and _Jv_MonitorExit() pop it off, I eliminated lots of try/catch block code
that only unlocked Java monitors.
The disadvantage to this mechanism is the overhead of pushing and popping
the exception stack. Yeah, it's similar conceptually to the sjlj support
currently in gcc, but it is not inlined. IMHO, the inlining of the sjlj
exception support is what contributes to most of the code bloat and buggyness
that the implementation currently suffers.
 -- 
Jon Olson, Modular Mining Systems
	 3289 E. Hemisphere Loop
	 Tucson, AZ 85706
INTERNET: olson@mmsi.com
PHONE: (520)746-9127
FAX: (520)889-5790


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /