void __rethrow(void *index) { struct eh_context *eh = (*get_eh_context) (); void *pc, *handler; long offset; frame_state my_ustruct, *my_udata = &my_ustruct; if (! eh->info) { __terminate (); } eh->table_index = index; label: my_udata = __frame_state_for (&&label, my_udata); if (! my_udata) { __terminate (); } my_udata->cfa = __builtin_dwarf_cfa (); __builtin_unwind_init (); pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1; handler = throw_helper (eh, pc, my_udata, &offset); __builtin_eh_return ((void *)eh, offset, handler); }
static void runtime_mcall(void (*pfn)(G*)) { #ifndef USING_SPLIT_STACK int i; #endif // Ensure that all registers are on the stack for the garbage // collector. __builtin_unwind_init(); if(g == m->g0) runtime_throw("runtime: mcall called on m->g0 stack"); if(g != nil) { #ifdef USING_SPLIT_STACK __splitstack_getcontext(&g->stack_context[0]); #else g->gcnext_sp = &i; #endif g->fromgogo = false; getcontext(&g->context); } if (g == nil || !g->fromgogo) { #ifdef USING_SPLIT_STACK __splitstack_setcontext(&m->g0->stack_context[0]); #endif m->g0->entry = (byte*)pfn; m->g0->param = g; g = m->g0; setcontext(&m->g0->context); runtime_throw("runtime: mcall function returned"); } }
/* ctxt is either a pointer to a ucontext_t we generated, or NULL. */ void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), ptr_t arg) { word dummy; void * context = 0; # if defined(HAVE_PUSH_REGS) GC_push_regs(); # elif defined(UNIX_LIKE) && !defined(DARWIN) && !defined(ARM32) /* Older versions of Darwin seem to lack getcontext(). */ /* ARM Linux often doesn't support a real getcontext(). */ ucontext_t ctxt; if (getcontext(&ctxt) < 0) ABORT ("Getcontext failed: Use another register retrieval method?"); context = &ctxt; # if defined(SPARC) || defined(IA64) /* On a register window machine, we need to save register */ /* contents on the stack for this to work. This may already be */ /* subsumed by the getcontext() call. */ { GC_save_regs_ret_val = GC_save_regs_in_stack(); } # endif /* register windows. */ # elif defined(HAVE_BUILTIN_UNWIND_INIT) /* This was suggested by Richard Henderson as the way to */ /* force callee-save registers and register windows onto */ /* the stack. */ __builtin_unwind_init(); # else /* !HAVE_BUILTIN_UNWIND_INIT && !UNIX_LIKE */ /* && !HAVE_PUSH_REGS */ /* Generic code */ /* The idea is due to Parag Patel at HP. */ /* We're not sure whether he would like */ /* to be he acknowledged for it or not. */ jmp_buf regs; register word * i = (word *) regs; register ptr_t lim = (ptr_t)(regs) + (sizeof regs); /* Setjmp doesn't always clear all of the buffer. */ /* That tends to preserve garbage. Clear it. */ for (; (char *)i < lim; i++) { *i = 0; } # if defined(MSWIN32) || defined(MSWINCE) \ || defined(UTS4) || defined(LINUX) || defined(EWS4800) (void) setjmp(regs); # else (void) _setjmp(regs); /* We don't want to mess with signals. According to */ /* SUSV3, setjmp() may or may not save signal mask. */ /* _setjmp won't, but is less portable. */ # endif # endif /* !HAVE_PUSH_REGS ... */ fn(arg, context); /* Strongly discourage the compiler from treating the above */ /* as a tail-call, since that would pop the register */ /* contents before we get a chance to look at them. */ GC_noop1((word)(&dummy)); }
static void runtime_mcall(void (*pfn)(G*)) { M *mp; G *gp; #ifndef USING_SPLIT_STACK int i; #endif // Ensure that all registers are on the stack for the garbage // collector. __builtin_unwind_init(); mp = m; gp = g; if(gp == mp->g0) runtime_throw("runtime: mcall called on m->g0 stack"); if(gp != nil) { #ifdef USING_SPLIT_STACK __splitstack_getcontext(&g->stack_context[0]); #else gp->gcnext_sp = &i; #endif gp->fromgogo = false; getcontext(&gp->context); // When we return from getcontext, we may be running // in a new thread. That means that m and g may have // changed. They are global variables so we will // reload them, but the addresses of m and g may be // cached in our local stack frame, and those // addresses may be wrong. Call functions to reload // the values for this thread. mp = runtime_m(); gp = runtime_g(); if(gp->traceback != nil) gtraceback(gp); } if (gp == nil || !gp->fromgogo) { #ifdef USING_SPLIT_STACK __splitstack_setcontext(&mp->g0->stack_context[0]); #endif mp->g0->entry = (byte*)pfn; mp->g0->param = gp; // It's OK to set g directly here because this case // can not occur if we got here via a setcontext to // the getcontext call just above. g = mp->g0; fixcontext(&mp->g0->context); setcontext(&mp->g0->context); runtime_throw("runtime: mcall function returned"); } }
void VMPI_callWithRegistersSaved(void (*fn)(void* stackPointer, void* arg), void* arg) { #if defined MMGC_IA32 void* buf = NULL; __builtin_unwind_init(); // Save registers - GCC intrinsic. Not reliable on 10.4 PPC or 64-bit #else jmp_buf buf; VMPI_setjmpNoUnwind(buf); // Save registers - not always reliable #endif CallWithRegistersSaved2(fn, arg, &buf); // Computes the stack pointer, calls fn CallWithRegistersSaved3(fn, &arg, &buf); // Probably prevents the previous call from being a tail call }
NOCOMPRESSION void foo (int x) { __builtin_unwind_init (); __builtin_eh_return (x, bar); }
void VMPI_callWithRegistersSaved(void (*fn)(void* stackPointer, void* arg), void* arg) { __builtin_unwind_init(); // Save registers - GCC intrinsic CallWithRegistersSaved2(fn, arg, NULL); // Computes the stack pointer, calls fn CallWithRegistersSaved3(fn, &arg, NULL); // Probably prevents the previous call from being a tail call }
void foo(void) { __builtin_unwind_init (); setup_offset(); __builtin_eh_return (offset, handler); }