Affix
view release on metacpan or search on metacpan
infix/src/jit/trampoline.c view on Meta::CPAN
goto cleanup;
}
handle->is_direct_trampoline = true; // Mark this as a direct marshalling trampoline.
size_t required_metadata_size = _estimate_metadata_size(temp_arena, return_type, arg_types, num_args);
handle->arena = infix_arena_create(required_metadata_size + INFIX_TRAMPOLINE_HEADROOM);
handle->is_external_arena = false;
if (handle->arena == nullptr) {
status = INFIX_ERROR_ALLOCATION_FAILED;
goto cleanup;
}
handle->return_type = _copy_type_graph_to_arena(handle->arena, return_type);
if (num_args > 0) {
handle->arg_types = infix_arena_alloc(handle->arena, sizeof(infix_type *) * num_args, _Alignof(infix_type *));
if (!handle->arg_types) {
status = INFIX_ERROR_ALLOCATION_FAILED;
goto cleanup;
}
for (size_t i = 0; i < num_args; ++i) {
handle->arg_types[i] = _copy_type_graph_to_arena(handle->arena, arg_types[i]);
if (arg_types[i] && !handle->arg_types[i] && !handle->arena->error) {
status = INFIX_ERROR_ALLOCATION_FAILED;
goto cleanup;
}
}
}
handle->num_args = num_args;
handle->num_fixed_args = num_args; // Direct trampolines are always fixed-arity.
handle->target_fn = target_fn;
handle->ref_count = 1;
// 4. Allocate and Finalize Executable Memory
handle->exec = infix_executable_alloc(buf.size);
if (handle->exec.rw_ptr == nullptr) {
status = INFIX_ERROR_ALLOCATION_FAILED;
goto cleanup;
}
infix_memcpy(handle->exec.rw_ptr, buf.code, buf.size);
if (!infix_executable_make_executable(
&handle->exec, INFIX_EXECUTABLE_DIRECT, layout->prologue_size, layout->epilogue_offset)) {
status = INFIX_ERROR_PROTECTION_FAILED;
goto cleanup;
}
infix_dump_hex(handle->exec.rx_ptr, handle->exec.size, "Direct-Marshalling Forward Trampoline Machine Code");
*out_trampoline = handle;
cleanup:
if (status != INFIX_SUCCESS && handle != nullptr)
infix_forward_destroy(handle);
infix_arena_destroy(temp_arena);
return status;
}
/**
* @brief Creates a bound forward trampoline from `infix_type` objects (Manual API).
*
* @details This is the lower-level, programmatic way to create a bound forward trampoline.
* It bypasses the signature string parser, making it suitable for performance-critical
* applications or language bindings that construct type information dynamically.
*
* All `infix_type` objects passed to this function must be fully resolved and have
* a valid layout. They should be allocated from a user-managed `infix_arena_t`.
*
* @param[out] out_trampoline Receives the created trampoline handle.
* @param[in] return_type The `infix_type` for the function's return value.
* @param[in] arg_types An array of `infix_type*` for the function's arguments.
* @param[in] num_args The number of arguments.
* @param[in] num_fixed_args The number of non-variadic arguments.
* @param[in] target_function The address of the C function to call.
* @return `INFIX_SUCCESS` on success.
*/
INFIX_API c23_nodiscard infix_status infix_forward_create_manual(infix_forward_t ** out_trampoline,
infix_type * return_type,
infix_type ** arg_types,
size_t num_args,
size_t num_fixed_args,
void * target_function) {
// This is part of the "Manual API". It calls the internal implementation directly
// without involving the signature parser. `source_arena` is null because the
// types are assumed to be managed by the user.
_infix_clear_error();
return _infix_forward_create_impl(
out_trampoline, nullptr, return_type, arg_types, num_args, num_fixed_args, target_function, false);
}
/**
* @brief Creates an unbound forward trampoline from `infix_type` objects (Manual API).
*
* @details This is the lower-level, programmatic way to create an unbound forward trampoline.
* It bypasses the signature string parser.
*
* @param[out] out_trampoline Receives the created trampoline handle.
* @param[in] return_type The `infix_type` for the function's return value.
* @param[in] arg_types An array of `infix_type*` for the function's arguments.
* @param[in] num_args The number of arguments.
* @param[in] num_fixed_args The number of non-variadic arguments.
* @return `INFIX_SUCCESS` on success.
*/
INFIX_API c23_nodiscard infix_status infix_forward_create_unbound_manual(infix_forward_t ** out_trampoline,
infix_type * return_type,
infix_type ** arg_types,
size_t num_args,
size_t num_fixed_args) {
_infix_clear_error();
return _infix_forward_create_impl(
out_trampoline, nullptr, return_type, arg_types, num_args, num_fixed_args, nullptr, false);
}
/**
* @internal
* @brief Internal implementation of forward trampoline destruction.
*/
void _infix_forward_destroy_internal(infix_forward_t * trampoline) {
if (trampoline == nullptr)
return;
// Destroying the private arena frees all deep-copied type metadata and the signature string.
if (trampoline->arena && !trampoline->is_external_arena)
infix_arena_destroy(trampoline->arena);
// Free the JIT-compiled executable code.
infix_executable_free(trampoline->exec);
// Free the handle struct itself.
( run in 0.612 second using v1.01-cache-2.11-cpan-2398b32b56e )