Affix

 view release on metacpan or  search on metacpan

lib/Affix.c  view on Meta::CPAN


    if (old_pin->destructor_lib_sv) {
#ifdef USE_ITHREADS
        new_pin->destructor_lib_sv = sv_dup(old_pin->destructor_lib_sv, param);
#else
        new_pin->destructor_lib_sv = old_pin->destructor_lib_sv;
#endif
        SvREFCNT_inc(new_pin->destructor_lib_sv);
    }

    // Handle type arena (Deep Copy)
    if (old_pin->type_arena && old_pin->type) {
        new_pin->type_arena = infix_arena_create(4096);
        new_pin->type = _copy_type_graph_to_arena(new_pin->type_arena, old_pin->type);
    }
    else {
        // Likely a raw void* or simple cast where arena wasn't used/needed
        new_pin->type = old_pin->type;
        new_pin->type_arena = nullptr;
    }
    mg->mg_ptr = (char *)new_pin;
    return 1;
}

// Handles UTF-16LE (Windows) and UTF-32 (Linux/Mac) conversion to UTF-8 SV
static void pull_pointer_as_wstring(pTHX_ Affix * affix, SV * sv, const infix_type * type, void * ptr) {
    PERL_UNUSED_VAR(affix);
    PERL_UNUSED_VAR(type);

    wchar_t * wstr = *(wchar_t **)ptr;

    if (wstr == nullptr) {
        sv_setsv(sv, &PL_sv_undef);
        return;
    }

    // Calculate length (like wcslen)
    size_t wlen = 0;
    while (wstr[wlen])
        wlen++;

    // Pre-allocate SV buffer.
    // Worst case UTF-8 expansion: 1 wchar (4 bytes) -> 4 UTF-8 bytes.
    // +1 for null terminator.
    SvGROW(sv, (wlen * sizeof(wchar_t)) + 1);

    char * d = SvPVX(sv);
    wchar_t * s = wstr;

    while (*s) {
        UV uv = (UV)*s++;

        // Handle Windows Surrogate Pairs (UTF-16LE)
        if (sizeof(wchar_t) == 2 && uv >= 0xD800 && uv <= 0xDBFF) {
            if (*s >= 0xDC00 && *s <= 0xDFFF) {
                UV low = (UV)*s++;
                uv = ((uv - 0xD800) << 10) + (low - 0xDC00) + 0x10000;
            }
        }

        d = (char *)uvchr_to_utf8((U8 *)d, uv);
    }
    *d = 0;

    // Set Perl SV properties
    SvCUR_set(sv, d - SvPVX(sv));
    SvPOK_on(sv);
    SvUTF8_on(sv);
}

// Direct marshalling experiment
// Forward declarations for static helpers
static infix_direct_value_t affix_marshaller_sint(void * sv_raw);
static infix_direct_value_t affix_marshaller_uint(void * sv_raw);
static infix_direct_value_t affix_marshaller_double(void * sv_raw);
static infix_direct_value_t affix_marshaller_pointer(void * sv_raw);
static void affix_aggregate_marshaller(void * sv_raw, void * dest, const infix_type * type);
static void affix_aggregate_writeback(void * sv_raw, void * src, const infix_type * type);
static infix_direct_arg_handler_t get_direct_handler_for_type(const infix_type * type);

void Affix_trigger_backend(pTHX_ CV * cv) {
    // Backend optimization is not yet thread-clone friendly in this patch.
    // For now, assume it works or isn't used in the threading test.
    dSP;
    dAXMARK;
    dXSTARG;

    Affix_Backend * backend = (Affix_Backend *)CvXSUBANY(cv).any_ptr;

    if (UNLIKELY((SP - MARK) != backend->num_args))
        croak("Wrong number of arguments to affixed function. Expected %" UVuf ", got %" UVuf,
              (UV)backend->num_args,
              (UV)(SP - MARK));

    void * ret_buffer = alloca(infix_type_get_size(backend->ret_type));
    SV ** perl_stack_frame = &ST(0);

    backend->cif(ret_buffer, (void **)perl_stack_frame);

    switch (backend->ret_opcode) {
    case OP_RET_VOID:
        sv_setsv(TARG, &PL_sv_undef);
        break;
    case OP_RET_BOOL:
        sv_setbool(TARG, *(bool *)ret_buffer);
        break;
    case OP_RET_SINT8:
        sv_setiv(TARG, *(int8_t *)ret_buffer);
        break;
    case OP_RET_UINT8:
        sv_setuv(TARG, *(uint8_t *)ret_buffer);
        break;
    case OP_RET_SINT16:
        sv_setiv(TARG, *(int16_t *)ret_buffer);
        break;
    case OP_RET_UINT16:
        sv_setuv(TARG, *(uint16_t *)ret_buffer);
        break;
    case OP_RET_SINT32:
        sv_setiv(TARG, *(int32_t *)ret_buffer);
        break;

lib/Affix.c  view on Meta::CPAN

            U32 flags = SvFLAGS(sv);                                                                         \
            if (LIKELY(flags & SVf_NOK))                                                                     \
                *(float *)ptr = (float)SvNVX(sv);                                                            \
            else if (flags & SVf_IOK)                                                                        \
                *(float *)ptr = (float)((flags & SVf_IVisUV) ? SvUVX(sv) : SvIVX(sv));                       \
            else                                                                                             \
                *(float *)ptr = (float)SvNV(sv);                                                             \
            c_args[step->data.index] = ptr;                                                                  \
            DISPATCH();                                                                                      \
        }                                                                                                    \
CASE_OP_PUSH_DOUBLE:                                                                                         \
        {                                                                                                    \
            SV * sv = ST(step->data.index);                                                                  \
            void * ptr = (char *)args_buffer + step->data.c_arg_offset;                                      \
            U32 flags = SvFLAGS(sv);                                                                         \
            if (LIKELY(flags & SVf_NOK))                                                                     \
                *(double *)ptr = SvNVX(sv);                                                                  \
            else if (flags & SVf_IOK)                                                                        \
                *(double *)ptr = (double)((flags & SVf_IVisUV) ? SvUVX(sv) : SvIVX(sv));                     \
            else                                                                                             \
                *(double *)ptr = (double)SvNV(sv);                                                           \
            c_args[step->data.index] = ptr;                                                                  \
            DISPATCH();                                                                                      \
        }                                                                                                    \
CASE_OP_PUSH_LONGDOUBLE:                                                                                     \
        {                                                                                                    \
            SV * sv = ST(step->data.index);                                                                  \
            void * ptr = (char *)args_buffer + step->data.c_arg_offset;                                      \
            U32 flags = SvFLAGS(sv);                                                                         \
            if (LIKELY(flags & SVf_NOK))                                                                     \
                *(long double *)ptr = SvNVX(sv);                                                             \
            else if (flags & SVf_IOK)                                                                        \
                *(long double *)ptr = (long double)((flags & SVf_IVisUV) ? SvUVX(sv) : SvIVX(sv));           \
            else                                                                                             \
                *(long double *)ptr = (long double)SvNV(sv);                                                 \
            c_args[step->data.index] = ptr;                                                                  \
            DISPATCH();                                                                                      \
        }                                                                                                    \
CASE_OP_PUSH_PTR_CHAR:                                                                                       \
        {                                                                                                    \
            SV * sv = ST(step->data.index);                                                                  \
            void * ptr = (char *)args_buffer + step->data.c_arg_offset;                                      \
            c_args[step->data.index] = ptr;                                                                  \
            if (SvPOK(sv))                                                                                   \
                *(const char **)ptr = SvPV_nolen(sv);                                                        \
            else if (!SvOK(sv))                                                                              \
                *(void **)ptr = nullptr;                                                                     \
            else if (is_pin(aTHX_ sv))                                                                       \
                *(void **)ptr = _get_pin_from_sv(aTHX_ sv)->pointer;                                         \
            else                                                                                             \
                step->executor(aTHX_ affix, step, &ST(0), args_buffer, c_args, ret_buffer);                  \
            DISPATCH();                                                                                      \
        }                                                                                                    \
CASE_OP_PUSH_PTR_WCHAR:                                                                                      \
        {                                                                                                    \
            SV * sv = ST(step->data.index);                                                                  \
            void * ptr = (char *)args_buffer + step->data.c_arg_offset;                                      \
            c_args[step->data.index] = ptr;                                                                  \
            if (SvPOK(sv)) {                                                                                 \
                STRLEN len;                                                                                  \
                U8 * s = (U8 *)SvPVutf8(sv, len);                                                            \
                U8 * e = s + len;                                                                            \
                Newx(*(void **)ptr, len + 1, wchar_t);                                                       \
                wchar_t * d = *(void **)ptr;                                                                 \
                while (s < e) {                                                                              \
                    UV uv = utf8_to_uvchr_buf(s, e, nullptr);                                                \
                    if (sizeof(wchar_t) == 2 && uv > 0xFFFF) {                                               \
                        uv -= 0x10000;                                                                       \
                        *d++ = (wchar_t)((uv >> 10) + 0xD800);                                               \
                        *d++ = (wchar_t)((uv & 0x3FF) + 0xDC00);                                             \
                    }                                                                                        \
                    else                                                                                     \
                        *d++ = (wchar_t)uv;                                                                  \
                    s += UTF8SKIP(s);                                                                        \
                }                                                                                            \
                *d = 0;                                                                                      \
                SAVEFREEPV(*(void **)ptr);                                                                   \
            }                                                                                                \
            else if (!SvOK(sv))                                                                              \
                *(void **)ptr = nullptr;                                                                     \
            else if (is_pin(aTHX_ sv))                                                                       \
                *(void **)ptr = _get_pin_from_sv(aTHX_ sv)->pointer;                                         \
            else                                                                                             \
                step->executor(aTHX_ affix, step, &ST(0), args_buffer, c_args, ret_buffer);                  \
            DISPATCH();                                                                                      \
        }                                                                                                    \
CASE_OP_PUSH_POINTER:                                                                                        \
        {                                                                                                    \
            SV * sv = ST(step->data.index);                                                                  \
            void * ptr = (char *)args_buffer + step->data.c_arg_offset;                                      \
            c_args[step->data.index] = ptr;                                                                  \
            if (is_pin(aTHX_ sv))                                                                            \
                *(void **)ptr = _get_pin_from_sv(aTHX_ sv)->pointer;                                         \
            else if (!SvOK(sv) && SvREADONLY(sv))                                                            \
                *(void **)ptr = nullptr;                                                                     \
            else                                                                                             \
                step->executor(aTHX_ affix, step, &ST(0), args_buffer, c_args, ret_buffer);                  \
            DISPATCH();                                                                                      \
        }                                                                                                    \
CASE_OP_PUSH_SV:                                                                                             \
        {                                                                                                    \
            SV * sv = ST(step->data.index);                                                                  \
            void * ptr = (char *)args_buffer + step->data.c_arg_offset;                                      \
            c_args[step->data.index] = ptr;                                                                  \
            *(SV **)ptr = sv;                                                                                \
            DISPATCH();                                                                                      \
        }                                                                                                    \
CASE_OP_PUSH_VECTOR:                                                                                         \
        {                                                                                                    \
            SV * sv = ST(step->data.index);                                                                  \
            void * ptr = (char *)args_buffer + step->data.c_arg_offset;                                      \
            c_args[step->data.index] = ptr;                                                                  \
            if (SvPOK(sv)) {                                                                                 \
                STRLEN len;                                                                                  \
                const char * buf = SvPV(sv, len);                                                            \
                size_t sz = infix_type_get_size(step->data.type);                                            \
                if (len >= sz) {                                                                             \
                    memcpy(ptr, buf, sz);                                                                    \
                    DISPATCH();                                                                              \
                }                                                                                            \
            }                                                                                                \
            step->executor(aTHX_ affix, step, &ST(0), args_buffer, c_args, ret_buffer);                      \
            DISPATCH();                                                                                      \
        }                                                                                                    \
CASE_OP_PUSH_STRUCT:                                                                                         \
CASE_OP_PUSH_UNION:                                                                                          \



( run in 2.082 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )