Affix

 view release on metacpan or  search on metacpan

infix/src/jit/executor.c  view on Meta::CPAN

        _infix_set_system_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_PROTECTION_FAILURE, GetLastError(), nullptr);
#else
    result = (mprotect(prot.rw_ptr, prot.size, PROT_READ) == 0);
    if (!result)
        _infix_set_system_error(INFIX_CATEGORY_ABI, INFIX_CODE_PROTECTION_FAILURE, errno, nullptr);
#endif
    return result;
}
// Universal Reverse Call Dispatcher
/**
 * @internal
 * @brief The universal C entry point for all reverse call trampolines.
 *
 * @details The JIT-compiled stub for a reverse call performs the minimal work of
 * marshalling all arguments from their native ABI locations (registers and stack)
 * into a standard `void**` array on its own stack. It then calls this function.
 *
 * This dispatcher inspects the `infix_reverse_t` context and takes one of two paths:
 *
 * 1.  **Type-Safe Callback Path:** If `cached_forward_trampoline` is not null, it
 *     means this is a type-safe callback. The dispatcher uses this pre-generated
 *     forward trampoline to call the user's C handler, which has a clean, native
 *     C function signature.
 *
 * 2.  **Generic Closure Path:** If there is no cached trampoline, it's a generic
 *     closure. The dispatcher directly calls the user's generic handler function,
 *     passing it the context, return buffer, and the `void**` args array.
 *
 * @param context The `infix_reverse_t` context for this call.
 * @param return_value_ptr A pointer to the stack buffer where the return value must be written.
 * @param args_array A pointer to the `void**` array of argument pointers.
 */
void infix_internal_dispatch_callback_fn_impl(infix_reverse_t * context, void * return_value_ptr, void ** args_array) {
    INFIX_DEBUG_PRINTF("Dispatching reverse call. Context: %p, User Fn: %p, ret=%p, args=%p",
                       (void *)context,
                       context->user_callback_fn,
                       return_value_ptr,
                       (void *)args_array);
    if (args_array) {
        for (size_t i = 0; i < context->num_args; i++) {
            INFIX_DEBUG_PRINTF(
                "  args[%zu] = %p (val: 0x%04X)", i, args_array[i], args_array[i] ? *(uint16_t *)args_array[i] : 0);
        }
    }
    if (context->user_callback_fn == nullptr) {
        // If no handler is set, do nothing. If the function has a return value,
        // it's good practice to zero it out to avoid returning garbage.
        if (return_value_ptr && context->return_type->size > 0)
            infix_memset(return_value_ptr, 0, context->return_type->size);
        return;
    }
    if (context->cached_forward_trampoline != nullptr) {
        // Path 1: Type-safe "callback". Use the pre-generated forward trampoline to
        // call the user's C function with the correct signature. This is efficient
        // and provides a clean interface for the C developer.
        infix_cif_func cif_func = infix_forward_get_code(context->cached_forward_trampoline);
        cif_func(return_value_ptr, args_array);
    }
    else {
        // Path 2: Generic "closure". Directly call the user's generic handler.
        // This path is more flexible and is intended for language bindings where the
        // handler needs access to the context and raw argument pointers.
        infix_closure_handler_fn handler = (infix_closure_handler_fn)context->user_callback_fn;
        handler(context, return_value_ptr, args_array);
    }
    INFIX_DEBUG_PRINTF("Exiting reverse call dispatcher.");
}



( run in 1.579 second using v1.01-cache-2.11-cpan-2398b32b56e )