Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ABI for unboxed calls from JITs (and cython, etc.) #474

Open
steve-s opened this issue Feb 1, 2024 · 0 comments
Open

ABI for unboxed calls from JITs (and cython, etc.) #474

steve-s opened this issue Feb 1, 2024 · 0 comments

Comments

@steve-s
Copy link
Contributor

steve-s commented Feb 1, 2024

Issue #129 is about API design for this feature, but the user-facing part can be tackled separately. HPy should provide ABI to Python interpreters that would give them:

  • pointer to "optimized" function that accepts (some) unboxed arguments
  • description of the signature of that function

Extension functions are described by HPyMeth C struct. We can just add necessary fields to it. From the API perspective, for the time being, we can let the users to define both entry points manually:.

Current API from proof-of-concept example:

HPyDef_METH(add_ints, "add_ints", HPyFunc_VARARGS)
static HPy add_ints_impl(HPyContext *ctx, HPy self, const HPy *args, size_t nargs)
{
    long a, b;
    if (!HPyArg_Parse(ctx, NULL, args, nargs, "ll", &a, &b))
        return HPy_NULL;
    return HPyLong_FromLong(ctx, a+b);
}

Could become:

HPyDef_METH(add_ints, "add_ints", HPyFunc_VARARGS, {Sig_int64, Sig_int64, Sig_int64})
static HPy add_ints_impl(HPyContext *ctx, HPy self, const HPy *args, size_t nargs)
{
    long a, b;
    if (!HPyArg_Parse(ctx, NULL, args, nargs, "ll", &a, &b))
        return HPy_NULL;
    return HPyLong_FromLong(ctx, add_ints_impl_unboxed(a, b));
}
static int64_t add_ints_impl_unboxed(HPyContext *ctx, HPy self, int64_t a, int64_t b) {
    return a+b;
}

where the macro HPyDef_METH would generate something along these lines:

HPyDef add_ints = {
    .kind=HPyDef_Kind_Meth, 
    .meth={
        .name="add_ints", 
        .impl=(HPyCFunction) add_ints_impl, 
        .unboxed_sig = {Sig_int64, Sig_int64, Sig_int64},
        .unboxed_impl = (HPyCFunction) add_ints_impl_unboxed,
        // ...

Python interpreters that implement HPy can choose to make calls either via .impl with boxed arguments, or via .unboxed_impl. Current, HPy implementation for CPython simply generates trampolines with CPython signature (*) that convert the PyObject* arguments to HPy, fish out HPyContext from a C global variable, and call .impl. Those trampolines are then used to set up the CPython PyModuleDef when loading HPy universal module on CPython. Once there is a support for "optimized" extension functions on CPython, this code in HPy can be updated to translate the HPy ABI to the CPython way of doing this. Current GraalPy implementation should be amenable to this design and I believe that PyPy's too.

(*) This happens as a part of the HPyDef_METH macro and there is a field for such trampoline in HPyMeth, so CPython backend is hard-coded into HPy a little bit, but that is necessary if we want to support CPython "externally" without backing HPy support into CPython core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant