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 )