예제 #1
0
void generatorEntry(BoxedGenerator* g) {
    {
        assert(g->cls == generator_cls);
        assert(g->function->cls == function_cls);

        threading::pushGenerator(g, g->stack_begin, g->returnContext);
        try {
            RegisterHelper context_registerer(g, __builtin_frame_address(0));

            // call body of the generator
            BoxedFunctionBase* func = g->function;

            Box** args = g->args ? &g->args->elts[0] : nullptr;
            callCLFunc<ExceptionStyle::CXX>(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g,
                                            func->globals, g->arg1, g->arg2, g->arg3, args);
        } catch (ExcInfo e) {
            // unhandled exception: propagate the exception to the caller
            g->exception = e;
        }

        // we returned from the body of the generator. next/send/throw will notify the caller
        g->entryExited = true;
        threading::popGenerator();
    }
    swapContext(&g->context, g->returnContext, 0);
}
예제 #2
0
void generatorEntry(BoxedGenerator* g) noexcept {
    {
        assert(g->cls == generator_cls);
        assert(g->function->cls == function_cls);

        assert(g->returnValue == Py_None);
        Py_CLEAR(g->returnValue);

        {
            RegisterHelper context_registerer(g, __builtin_frame_address(0));

            g->top_caller_frame_info = (FrameInfo*)cur_thread_state.frame_info;

            // call body of the generator
            BoxedFunctionBase* func = g->function;
            // unnecessary because the generator owns g->function
            // KEEP_ALIVE(func);

            Box** args = g->args ? &g->args->elts[0] : nullptr;
            auto r = callCLFunc<ExceptionStyle::CAPI, NOT_REWRITABLE>(func->code, nullptr,
                     func->code->numReceivedArgs(), func->closure, g,
                     func->globals, g->arg1, g->arg2, g->arg3, args);
            if (r)
                Py_DECREF(r);
            else {
                // unhandled exception: propagate the exception to the caller
                PyErr_Fetch(&g->exception.type, &g->exception.value, &g->exception.traceback);
                PyErr_Clear();
            }
        }

        // we returned from the body of the generator. next/send/throw will notify the caller
        g->entryExited = true;
    }
    assert(g->top_caller_frame_info == cur_thread_state.frame_info);
    swapContext(&g->context, g->returnContext, 0);
}