⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eh.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * XXX add FSF copyright information here. XXX * * This file copies the exception handling related part from libgcc2.c * Specifically, the part that's compiled when -DL_eh is defined. *  * NB: This file is temporary, hopefully.  I'm lobbying for integrating * the "__frame_state_for_func" hook into libgcc2.c * * It was created from GCC's libgcc2.c by executing this command: * *   sed '/#ifdef L_eh/,/#endif \/\* L_eh \*\//p; d' \ *	 < "$1" | sed '1d;$d'  * * I have added this header to it: */ /* Begin of kaffe-specific configuration header */#include "config.h"#if defined(HAVE_GCJ_SUPPORT) && defined(JIT3) && defined(TRANSLATOR)#include "gtypes.h"#include "debug.h"#include "md.h"#include "gansidecl.h"/* End of kaffe-specific configuration header *//*----------------------------------------------------------------------*//* Shared exception handling support routines.  */extern void __default_terminate (void) __attribute__ ((__noreturn__));void__default_terminate (){  abort ();}void (*__terminate_func)() = __default_terminate;void__terminate (){  (*__terminate_func)();}void *__throw_type_match (void *catch_type, void *throw_type, void *obj){#if 0 printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",	 catch_type, throw_type);#endif if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)   return obj; return 0;}void__empty (){}/* Include definitions of EH context and table layout */#include "eh-common.h"#ifndef inhibit_libc#include <stdio.h>#endif/* Allocate and return a new EH context structure. */extern void __throw ();static void *new_eh_context (){  struct eh_full_context {    struct eh_context c;    void *top_elt[2];  } *ehfc = (struct eh_full_context *) malloc (sizeof *ehfc);  if (! ehfc)    __terminate ();  memset (ehfc, 0, sizeof *ehfc);  ehfc->c.dynamic_handler_chain = (void **) ehfc->top_elt;  /* This should optimize out entirely.  This should always be true,     but just in case it ever isn't, don't allow bogus code to be     generated.  */  if ((void*)(&ehfc->c) != (void*)ehfc)    __terminate ();  return &ehfc->c;}#if __GTHREADSstatic __gthread_key_t eh_context_key;/* Destructor for struct eh_context. */static voideh_context_free (void *ptr){  __gthread_key_dtor (eh_context_key, ptr);  if (ptr)    free (ptr);}#endif/* Pointer to function to return EH context. */static struct eh_context *eh_context_initialize ();static struct eh_context *eh_context_static ();#if __GTHREADSstatic struct eh_context *eh_context_specific ();#endifstatic struct eh_context *(*get_eh_context) () = &eh_context_initialize;/* Routine to get EH context.   This one will simply call the function pointer. */void *__get_eh_context (){  return (void *) (*get_eh_context) ();}/* Get and set the language specific info pointer. */void **__get_eh_info (){  struct eh_context *eh = (*get_eh_context) ();  return &eh->info;}#ifdef DWARF2_UNWIND_INFOstatic int dwarf_reg_size_table_initialized = 0;static char dwarf_reg_size_table[FIRST_PSEUDO_REGISTER];static voidinit_reg_size_table (){  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);  dwarf_reg_size_table_initialized = 1;}#endif#if __GTHREADSstatic voideh_threads_initialize (){  /* Try to create the key.  If it fails, revert to static method,     otherwise start using thread specific EH contexts. */  if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)    get_eh_context = &eh_context_specific;  else    get_eh_context = &eh_context_static;}#endif /* no __GTHREADS *//* Initialize EH context.   This will be called only once, since we change GET_EH_CONTEXT   pointer to another routine. */static struct eh_context *eh_context_initialize (){#if __GTHREADS  static __gthread_once_t once = __GTHREAD_ONCE_INIT;  /* Make sure that get_eh_context does not point to us anymore.     Some systems have dummy thread routines in their libc that     return a success (Solaris 2.6 for example). */  if (__gthread_once (&once, eh_threads_initialize) != 0      || get_eh_context == &eh_context_initialize)    {      /* Use static version of EH context. */      get_eh_context = &eh_context_static;    }#ifdef DWARF2_UNWIND_INFO  {    static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;    if (__gthread_once (&once_regsizes, init_reg_size_table) != 0	|| ! dwarf_reg_size_table_initialized)      init_reg_size_table ();  }#endif#else /* no __GTHREADS */  /* Use static version of EH context. */  get_eh_context = &eh_context_static;#ifdef DWARF2_UNWIND_INFO  init_reg_size_table ();#endif#endif /* no __GTHREADS */  return (*get_eh_context) ();}/* Return a static EH context. */static struct eh_context *eh_context_static (){  static struct eh_context eh;  static int initialized;  static void *top_elt[2];  if (! initialized)    {      initialized = 1;      memset (&eh, 0, sizeof eh);      eh.dynamic_handler_chain = top_elt;    }  return &eh;}#if __GTHREADS/* Return a thread specific EH context. */static struct eh_context *eh_context_specific (){  struct eh_context *eh;  eh = (struct eh_context *) __gthread_getspecific (eh_context_key);  if (! eh)    {      eh = new_eh_context ();      if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)	__terminate ();    }  return eh;}#endif __GTHREADS/* Support routines for setjmp/longjmp exception handling.  *//* Calls to __sjthrow are generated by the compiler when an exception   is raised when using the setjmp/longjmp exception handling codegen   method.  */#ifdef DONT_USE_BUILTIN_SETJMPextern void longjmp (void *, int);#endif/* Routine to get the head of the current thread's dynamic handler chain   use for exception handling. */void ***__get_dynamic_handler_chain (){  struct eh_context *eh = (*get_eh_context) ();  return &eh->dynamic_handler_chain;}/* This is used to throw an exception when the setjmp/longjmp codegen   method is used for exception handling.   We call __terminate if there are no handlers left.  Otherwise we run the   cleanup actions off the dynamic cleanup stack, and pop the top of the   dynamic handler chain, and use longjmp to transfer back to the associated   handler.  */extern void __sjthrow (void) __attribute__ ((__noreturn__));void__sjthrow (){  struct eh_context *eh = (*get_eh_context) ();  void ***dhc = &eh->dynamic_handler_chain;  void *jmpbuf;  void (*func)(void *, int);  void *arg;  void ***cleanup;  /* The cleanup chain is one word into the buffer.  Get the cleanup     chain.  */  cleanup = (void***)&(*dhc)[1];  /* If there are any cleanups in the chain, run them now.  */  if (cleanup[0])    {      double store[200];      void **buf = (void**)store;      buf[1] = 0;      buf[0] = (*dhc);      /* try { */#ifdef DONT_USE_BUILTIN_SETJMP      if (! setjmp (&buf[2]))#else      if (! __builtin_setjmp (&buf[2]))#endif	{	  *dhc = buf;	  while (cleanup[0])	    {	      func = (void(*)(void*, int))cleanup[0][1];	      arg = (void*)cleanup[0][2];	      /* Update this before running the cleanup.  */	      cleanup[0] = (void **)cleanup[0][0];	      (*func)(arg, 2);	    }	  *dhc = buf[0];	}      /* catch (...) */      else	{	  __terminate ();	}    }    /* We must call terminate if we try and rethrow an exception, when     there is no exception currently active and when there are no     handlers left.  */  if (! eh->info || (*dhc)[0] == 0)    __terminate ();      /* Find the jmpbuf associated with the top element of the dynamic     handler chain.  The jumpbuf starts two words into the buffer.  */  jmpbuf = &(*dhc)[2];  /* Then we pop the top element off the dynamic handler chain.  */  *dhc = (void**)(*dhc)[0];  /* And then we jump to the handler.  */#ifdef DONT_USE_BUILTIN_SETJMP  longjmp (jmpbuf, 1);#else  __builtin_longjmp (jmpbuf, 1);#endif}/* Run cleanups on the dynamic cleanup stack for the current dynamic   handler, then pop the handler off the dynamic handler stack, and   then throw.  This is used to skip the first handler, and transfer   control to the next handler in the dynamic handler stack.  */extern void __sjpopnthrow (void) __attribute__ ((__noreturn__));void__sjpopnthrow (){  struct eh_context *eh = (*get_eh_context) ();  void ***dhc = &eh->dynamic_handler_chain;  void (*func)(void *, int);  void *arg;  void ***cleanup;  /* The cleanup chain is one word into the buffer.  Get the cleanup     chain.  */  cleanup = (void***)&(*dhc)[1];  /* If there are any cleanups in the chain, run them now.  */  if (cleanup[0])    {      double store[200];      void **buf = (void**)store;      buf[1] = 0;      buf[0] = (*dhc);      /* try { */#ifdef DONT_USE_BUILTIN_SETJMP      if (! setjmp (&buf[2]))#else      if (! __builtin_setjmp (&buf[2]))#endif	{	  *dhc = buf;	  while (cleanup[0])	    {	      func = (void(*)(void*, int))cleanup[0][1];	      arg = (void*)cleanup[0][2];	      /* Update this before running the cleanup.  */	      cleanup[0] = (void **)cleanup[0][0];	      (*func)(arg, 2);	    }	  *dhc = buf[0];	}      /* catch (...) */      else	{	  __terminate ();	}    }  /* Then we pop the top element off the dynamic handler chain.  */  *dhc = (void**)(*dhc)[0];  __sjthrow ();}/* Support code for all exception region-based exception handling.  */int__eh_rtime_match (void *rtime){  void *info;  __eh_matcher matcher;  void *ret;  info = *(__get_eh_info ());  matcher = ((__eh_info *)info)->match_function;  if (! matcher)    {#ifndef inhibit_libc      dprintf("Internal Compiler Bug: No runtime type matcher.");#endif      return 0;    }  ret = (*matcher) (info, rtime, (void *)0);  return (ret != NULL);}/* This value identifies the place from which an exception is being   thrown.  */#ifdef EH_TABLE_LOOKUPEH_TABLE_LOOKUP#else#ifdef DWARF2_UNWIND_INFO/* Return the table version of an exception descriptor */short __get_eh_table_version (exception_descriptor *table) {  return table->lang.version;}/* Return the originating table language of an exception descriptor */short __get_eh_table_language (exception_descriptor *table){  return table->lang.language;}/* This routine takes a PC and a pointer to the exception region TABLE for   its translation unit, and returns the address of the exception handler   associated with the closest exception table handler entry associated   with that PC, or 0 if there are no table entries the PC fits in.   In the advent of a tie, we have to give the last entry, as it represents   an inner block.  */static void *old_find_exception_handler (void *pc, old_exception_table *table){  if (table)    {      int pos;      int best = -1;      /* We can't do a binary search because the table isn't guaranteed         to be sorted from function to function.  */      for (pos = 0; table[pos].start_region != (void *) -1; ++pos)        {          if (table[pos].start_region <= pc && table[pos].end_region > pc)            {              /* This can apply.  Make sure it is at least as small as                 the previous best.  */              if (best == -1 || (table[pos].end_region <= table[best].end_region                        && table[pos].start_region >= table[best].start_region))                best = pos;            }          /* But it is sorted by starting PC within a function.  */          else if (best >= 0 && table[pos].start_region > pc)            break;        }      if (best != -1)        return table[best].exception_handler;    }  return (void *) 0;}/* find_exception_handler finds the correct handler, if there is one, to   handle an exception.   returns a pointer to the handler which controlled should be transferred   to, or NULL if there is nothing left.   Parameters:   PC - pc where the exception originates. If this is a rethrow,         then this starts out as a pointer to the exception table	entry we wish to rethrow out of.   TABLE - exception table for the current module.   EH_INFO - eh info pointer for this exception.   RETHROW - 1 if this is a rethrow. (see incoming value of PC).   CLEANUP - returned flag indicating whether this is a cleanup handler.*/static void *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -