OSDN Git Service

2007-02-09 Jakub Jelinek <jakub@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / exception.cc
index 16bbb9f..4875dfd 100644 (file)
@@ -1,6 +1,6 @@
 // Functions for Exception Support for Java.
 
-/* Copyright (C) 1998, 1999, 2001  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001, 2002, 2006  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -11,18 +11,27 @@ details.  */
 #include <config.h>
 
 #include <stddef.h>
-#include <cstdlib>
+#include <stdlib.h>
 
 #include <java/lang/Class.h>
 #include <java/lang/NullPointerException.h>
+#include <gnu/gcj/RawData.h> 
 #include <gcj/cni.h>
 #include <jvm.h>
 
+// unwind-pe.h uses std::abort(), but sometimes we compile libjava
+// without libstdc++-v3. The following hack forces it to use
+// stdlib.h's abort().
+namespace std
+{
+  static __attribute__ ((__noreturn__)) void
+  abort ()
+  {
+    ::abort ();
+  }
+}
 #include "unwind.h"
 
-#include <gc.h>
-
-\f
 struct alignment_test_struct
 {
   char space;
@@ -73,9 +82,8 @@ get_exception_header_from_ue (_Unwind_Exception *exc)
 extern "C" void
 _Jv_Throw (jthrowable value)
 {
-  /* FIXME: Use the proper API to the collector.  */
   java_exception_header *xh
-    = static_cast<java_exception_header *>(GC_malloc (sizeof (*xh)));
+    = static_cast<java_exception_header *>(_Jv_AllocRawObj (sizeof (*xh)));
 
   if (value == NULL)
     value = new java::lang::NullPointerException ();
@@ -100,7 +108,7 @@ _Jv_Throw (jthrowable value)
      recover.  As is the way of such things, almost certainly we will have
      crashed before now, rather than actually being able to diagnose the
      problem.  */
-  std::abort ();
+  abort();
 }
 
 \f
@@ -120,7 +128,7 @@ static const unsigned char *
 parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
                   lsda_header_info *info)
 {
-  _Unwind_Ptr tmp;
+  _uleb128_t tmp;
   unsigned char lpstart_encoding;
 
   info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
@@ -151,7 +159,7 @@ parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
   return p;
 }
 
-static jclass
+static void **
 get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
 {
   _Unwind_Ptr ptr;
@@ -159,7 +167,7 @@ get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
   i *= size_of_encoded_value (info->ttype_encoding);
   read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
 
-  return reinterpret_cast<jclass>(ptr);
+  return reinterpret_cast<void **>(ptr);
 }
 
 
@@ -189,6 +197,7 @@ PERSONALITY_FUNCTION (int version,
   int handler_switch_value;
   bool saw_cleanup;
   bool saw_handler;
+  int ip_before_insn = 0;
 
 
   // Interface version check.
@@ -204,10 +213,10 @@ PERSONALITY_FUNCTION (int version,
       goto install_context;
     }
 
-  // FIXME: In Phase 1, record _Unwind_GetIP in xh->obj as a part of
+  // FIXME: In Phase 1, record _Unwind_GetIPInfo in xh->obj as a part of
   // the stack trace for this exception.  This will only collect Java
   // frames, but perhaps that is acceptable.
-  // FIXME2: _Unwind_GetIP is nonsensical for SJLJ, being a call-site
+  // FIXME2: _Unwind_GetIPInfo is nonsensical for SJLJ, being a call-site
   // index instead of a PC value.  We could perhaps arrange for
   // _Unwind_GetRegionStart to return context->fc->jbuf[1], which
   // is the address of the handler label for __builtin_longjmp, but
@@ -222,7 +231,13 @@ PERSONALITY_FUNCTION (int version,
 
   // Parse the LSDA header.
   p = parse_lsda_header (context, language_specific_data, &info);
+#ifdef HAVE_GETIPINFO
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
+  if (! ip_before_insn)
+    --ip;
+#else
   ip = _Unwind_GetIP (context) - 1;
+#endif
   landing_pad = 0;
   action_record = 0;
   handler_switch_value = 0;
@@ -236,7 +251,7 @@ PERSONALITY_FUNCTION (int version,
     return _URC_CONTINUE_UNWIND;
   else
     {
-      _Unwind_Ptr cs_lp, cs_action;
+      _uleb128_t cs_lp, cs_action;
       do
        {
          p = read_uleb128 (p, &cs_lp);
@@ -255,7 +270,8 @@ PERSONALITY_FUNCTION (int version,
   // Search the call-site table for the action associated with this IP.
   while (p < info.action_table)
     {
-      _Unwind_Ptr cs_start, cs_len, cs_lp, cs_action;
+      _Unwind_Ptr cs_start, cs_len, cs_lp;
+      _uleb128_t cs_action;
 
       // Note that all call-site encodings are "absolute" displacements.
       p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
@@ -301,15 +317,13 @@ PERSONALITY_FUNCTION (int version,
   else
     {
       // Otherwise we have a catch handler.
-      signed long ar_filter, ar_disp;
+      _sleb128_t ar_filter, ar_disp;
 
       while (1)
        {
-         _Unwind_Ptr tmp;
-
          p = action_record;
-         p = read_sleb128 (p, &tmp); ar_filter = tmp;
-         read_sleb128 (p, &tmp); ar_disp = tmp;
+         p = read_sleb128 (p, &ar_filter);
+         read_sleb128 (p, &ar_disp);
 
          if (ar_filter == 0)
            {
@@ -327,12 +341,14 @@ PERSONALITY_FUNCTION (int version,
            {
              // Positive filter values are handlers.
 
-             jclass catch_type = get_ttype_entry (context, &info, ar_filter);
+             void **catch_word = get_ttype_entry (context, &info, ar_filter);
+             jclass catch_type = (jclass)*catch_word;
 
-             // The catch_type is either a (java::lang::Class*) or
-             // is one more than a (Utf8Const*).
-             if ((size_t)catch_type & 1)
-               catch_type = _Jv_FindClass ((Utf8Const*)catch_type - 1, NULL);
+             // FIXME: This line is a kludge to work around exception
+             // handlers written in C++, which don't yet use indirect
+             // dispatch.
+             if (catch_type == *(void **)&java::lang::Class::class$)
+               catch_type = (jclass)catch_word;
 
              if (_Jv_IsInstanceOf (xh->value, catch_type))
                {
@@ -348,7 +364,7 @@ PERSONALITY_FUNCTION (int version,
              // ??? Perhaps better to make them an index into a table
              // of null-terminated strings instead of playing games
              // with Utf8Const+1 as above.
-             std::abort ();
+             abort ();
            }
 
          if (ar_disp == 0)