+
+typedef struct PSI_LibjitContext {
+ jit_context_t jit;
+ jit_type_t signature;
+ struct {
+ struct PSI_LibjitData **list;
+ size_t count;
+ } data;
+} PSI_LibjitContext;
+
+typedef struct PSI_LibjitCall {
+ void *closure;
+ jit_type_t signature;
+ void *params[1]; /* [type1, type2, NULL, arg1, arg2] ... */
+} PSI_LibjitCall;
+
+typedef struct PSI_LibjitData {
+ PSI_LibjitContext *context;
+ impl *impl;
+ zend_internal_arg_info *arginfo;
+} PSI_LibjitData;
+
+static inline PSI_LibjitCall *PSI_LibjitCallAlloc(PSI_Context *C, decl *decl) {
+ size_t i, c = decl->args ? decl->args->count : 0;
+ PSI_LibjitCall *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *));
+
+ for (i = 0; i < c; ++i) {
+ call->params[i] = psi_jit_decl_arg_type(decl->args->args[i]);
+ }
+ call->params[c] = NULL;
+
+ decl->call.info = call;
+ decl->call.rval = &decl->func->ptr;
+ decl->call.argc = c;
+ decl->call.args = (void **) &call->params[c+1];
+
+ call->signature = jit_type_create_signature(
+ psi_jit_abi(decl->abi->convention),
+ psi_jit_decl_arg_type(decl->func),
+ (jit_type_t *) call->params, c, 1);
+ ZEND_ASSERT(call->signature);
+
+ return call;
+}
+
+static inline void *PSI_LibjitCallInitClosure(PSI_Context *C, PSI_LibjitCall *call, impl *impl) {
+ PSI_LibjitContext *context = C->context;
+ return call->closure = jit_closure_create(context->jit, context->signature,
+ &psi_jit_handler, impl);
+}
+
+static inline void *PSI_LibjitCallInitCallbackClosure(PSI_Context *C, PSI_LibjitCall *call, let_callback *cb) {
+ PSI_LibjitContext *context = C->context;
+ return call->closure = jit_closure_create(context->jit, call->signature,
+ &psi_jit_callback, cb);
+}
+
+static inline void PSI_LibjitCallFree(PSI_LibjitCall *call) {
+ jit_type_free(call->signature);
+ free(call);
+}
+
+static inline PSI_LibjitContext *PSI_LibjitContextInit(PSI_LibjitContext *L) {
+ jit_type_t params[] = {
+ jit_type_void_ptr,
+ jit_type_void_ptr
+ };
+
+ if (!L) {
+ L = malloc(sizeof(*L));
+ }
+ memset(L, 0, sizeof(*L));
+
+ L->jit = jit_context_create();
+ L->signature = jit_type_create_signature(jit_abi_cdecl, jit_type_void,
+ params, 2, 1);
+
+ return L;
+}
+
+static inline void PSI_LibjitContextDtor(PSI_LibjitContext *L) {
+ jit_type_free(L->signature);
+ jit_context_destroy(L->jit);
+}
+
+static inline void PSI_LibjitContextFree(PSI_LibjitContext **L) {
+ if (*L) {
+ PSI_LibjitContextDtor(*L);
+ free(*L);
+ *L = NULL;
+ }
+}
+
+static void psi_jit_init(PSI_Context *C)