------- Comment #14 from jakub at gcc dot gnu dot org 2008-10-24 13:53 ------- I think it is _Jv_divI which now has wrong unwind info (well, not only that). Here is a self-contained source for _Jv_divI:
#pragma GCC java_exceptions extern "Java" { typedef __java_int jint; typedef __java_long jlong; typedef __java_boolean jboolean; typedef jint jsize; namespace java { namespace lang { class Class; class Object; class String; class Throwable; } } } typedef struct java::lang::Object* jobject; typedef class java::lang::Class* jclass; typedef class java::lang::Throwable* jthrowable; typedef class java::lang::String* jstring; extern "C" jobject _Jv_AllocObject (jclass) __attribute__((__malloc__)); extern "C" void _Jv_Throw (jthrowable) __attribute__ ((__noreturn__)); extern "Java" { struct _JvObjectPrefix { virtual void nacd_1 (void) {}; }; } struct java::lang::Object : public _JvObjectPrefix { virtual void finalize (void); jclass getClass (void); virtual jint hashCode (void); void notify (void); void notifyAll (void); void wait (jlong timeout, jint nanos); virtual jboolean equals (jobject obj); Object (void); virtual jstring toString (void); void wait (void); void wait (jlong timeout); static java::lang::Class class$; virtual jobject clone (void); }; struct java::lang::Throwable : public ::java::lang::Object { Throwable(); Throwable(::java::lang::String *); static const jlong serialVersionUID = -3042686055658047285LL; ::java::lang::String * __attribute__((aligned(__alignof__( ::java::lang::Object)))) detailMessage; static ::java::lang::Class class$; }; extern "C" jstring bar(const char*, jsize) __attribute__((__malloc__)); jint _Jv_divI (jint dividend, jint divisor) { if (__builtin_expect (divisor == 0, false)) { java::lang::Throwable *arithexception = new java::lang::Throwable (bar ("/ by zero", 9)); throw arithexception; } if (dividend == (jint) 0x80000000L && divisor == -1) return dividend; return dividend / divisor; } compile this with -O2 and note that rp is only saved into a register in the non-throwing case: _Z8_Jv_divIii: [.LFB1:] .prologue 12, 34 .mmi .save ar.pfs, r35 alloc r35 = ar.pfs, 2, 3, 2, 0 .fframe 16 adds r12 = -16, r12 cmp4.ne p6, p7 = 0, r33 .mmb mov r36 = r1 mov r37 = r32 (p7) br.cond.spnt .L7 ;; .mib nop 0 .save rp, r34 mov r34 = b0 ... .L4: .mii nop 0 mov ar.pfs = r35 ;; mov b0 = r34 .mmb nop 0 .label_state 1 .restore sp adds r12 = 16, r12 br.ret.sptk.many b0 .L7: .body .copy_state 1 ... br.call.sptk.many b0 = bar# ... br.call.sptk.many b0 = _Jv_Throw# ;; break.f 0 ;; .endp _Z8_Jv_divIii# The code after .L7 doesn't ever branch to the normal code, and b0 is only saved into r34 around the normal codepath. So, after the first call after .L7 label the caller's rp isn't preserved anywhere. If none of the calls could ever throw, then that would just mean it would be impossible to print backtraces, but as some calls can throw (and the last, noreturn, call will always throw), not saving b0 into some local register is a bug. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37378