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

Reply via email to