Esempio n. 1
0
static inline NORETURN void resume(unw_cursor_t* cursor, const uint8_t* landing_pad, int64_t switch_value,
                                   const ExcInfo* exc_data) {
    checkExcInfo(exc_data);
    assert(landing_pad);
    if (VERBOSITY("cxx_unwind") >= 4)
        printf("  * RESUMED: ip %p  switch_value %ld\n", (const void*)landing_pad, (long)switch_value);

    if (0 != switch_value) {
        // The exception handler will call __cxa_begin_catch, which stops this timer and logs it.
        per_thread_resume_catch_timer.restart("resume_catch", 20);
    } else {
        // The cleanup code will call _Unwind_Resume, which will stop this timer and log it.
        // TODO: am I sure cleanup code can't raise exceptions? maybe have an assert!
        per_thread_cleanup_timer.restart("cleanup", 20);
#ifndef NDEBUG
        in_cleanup_code = true;
#endif
    }

    // set rax to pointer to exception object
    // set rdx to the switch_value (0 for cleanup, otherwise an index indicating which exception handler to use)
    //
    // NB. assumes x86-64. maybe I should use __builtin_eh_return_data_regno() here?
    // but then, need to translate into UNW_* values somehow. not clear how.
    check(unw_set_reg(cursor, UNW_X86_64_RAX, (unw_word_t)exc_data));
    check(unw_set_reg(cursor, UNW_X86_64_RDX, switch_value));

    // resume!
    check(unw_set_reg(cursor, UNW_REG_IP, (unw_word_t)landing_pad));
    unw_resume(cursor);
    RELEASE_ASSERT(0, "unw_resume returned!");
}
Esempio n. 2
0
extern "C" void __cxa_throw(void* exc_obj, std::type_info* tinfo, void (*dtor)(void*)) {
    static pyston::StatCounter num_cxa_throw("num_cxa_throw");
    num_cxa_throw.log();

    assert(!pyston::in_cleanup_code);
    assert(exc_obj);
    RELEASE_ASSERT(tinfo == &EXCINFO_TYPE_INFO, "can't throw a non-ExcInfo value! type info: %p", tinfo);

    if (VERBOSITY("cxx_unwind") >= 4)
        printf("***** __cxa_throw() *****\n");

    pyston::ExcInfo* exc_data = (pyston::ExcInfo*)exc_obj;
    checkExcInfo(exc_data);

    ASSERT(!pyston::is_unwinding, "We don't support throwing exceptions in destructors!");

    pyston::is_unwinding = true;
#if STAT_TIMERS
    pyston::StatTimer::overrideCounter(unwinding_stattimer);
#endif

    // let unwinding.cpp know we've started unwinding
    pyston::logException(exc_data);
    pyston::unwind(exc_data);
}
Esempio n. 3
0
// Takes the value that resume() sent us in RAX, and returns a pointer to the exception object actually thrown. In our
// case, these are the same, and should always be &pyston::exception_ferry.
extern "C" void* __cxa_begin_catch(void* exc_obj_in) noexcept {
    assert(exc_obj_in);
    pyston::us_unwind_resume_catch.log(pyston::per_thread_resume_catch_timer.end());

    if (VERBOSITY("cxx_unwind") >= 4)
        printf("***** __cxa_begin_catch() *****\n");

    pyston::ExcInfo* e = (pyston::ExcInfo*)exc_obj_in;
    checkExcInfo(e);
    return e;
}
Esempio n. 4
0
extern "C" void __cxa_throw(void* exc_obj, std::type_info* tinfo, void (*dtor)(void*)) {
    assert(!pyston::in_cleanup_code);
    assert(exc_obj);
    RELEASE_ASSERT(tinfo == &EXCINFO_TYPE_INFO, "can't throw a non-ExcInfo value! type info: %p", tinfo);

    if (VERBOSITY("cxx_unwind") >= 4)
        printf("***** __cxa_throw() *****\n");

    pyston::ExcInfo* exc_data = (pyston::ExcInfo*)exc_obj;
    checkExcInfo(exc_data);

#if STAT_TIMERS
    pyston::StatTimer::overrideCounter(unwinding_stattimer);
#endif
    // let unwinding.cpp know we've started unwinding
    pyston::throwingException(pyston::getActivePythonUnwindSession());
    pyston::unwind(exc_data);
}
Esempio n. 5
0
extern "C" void* __cxa_get_exception_ptr(void* exc_obj_in) noexcept {
    assert(exc_obj_in);
    pyston::ExcInfo* e = (pyston::ExcInfo*)exc_obj_in;
    checkExcInfo(e);
    return e;
}
Esempio n. 6
0
// The unwinder entry-point.
static void unwind(ExcInfo* exc) {
    checkExcInfo(exc);
    unwind_loop(exc);
    // unwind_loop returned, couldn't find any handler. ruh-roh.
    panic();
}