#include <ffi.h>
+#ifndef PSI_HAVE_FFI_CLOSURE_ALLOC
+# if HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+# if HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+# ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+# endif
+#endif
+
+static void *psi_ffi_closure_alloc(size_t s, void **code)
+{
+#ifdef PSI_HAVE_FFI_CLOSURE_ALLOC
+ return ffi_closure_alloc(s, code);
+#elif HAVE_MMAP
+ *code = mmap(NULL, s, PROT_EXEC|PROT_WRITE|PROT_READ,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (MAP_FAILED == *code) {
+ return NULL;
+ }
+ return *code;
+#else
+ return NULL;
+#endif
+}
+
+static void psi_ffi_closure_free(void *c)
+{
+#ifdef PSI_HAVE_FFI_CLOSURE_ALLOC
+ ffi_closure_free(c);
+#elif HAVE_MMAP
+ munmap(c, sizeof(ffi_closure));
+#endif
+}
+
static void handler(ffi_cif *signature, void *_result, void **_args, void *_data);
static inline ffi_abi psi_ffi_abi(const char *convention) {
psi_ffi_decl_arg_type(data->impl->decl->func),
data->params);
ZEND_ASSERT(FFI_OK == rc);
- data->closure = ffi_closure_alloc(sizeof(ffi_closure), &data->code);
+
+ data->closure = psi_ffi_closure_alloc(sizeof(ffi_closure), &data->code);
+ ZEND_ASSERT(data->closure != NULL);
+#if PSI_HAVE_FFI_PREP_CLOSURE_LOC
rc = ffi_prep_closure_loc(
data->closure,
&context->signature,
data,
data->code);
ZEND_ASSERT(FFI_OK == rc);
+#elif PSI_HAVE_FFI_PREP_CLOSURE
+ rc = ffi_prep_closure(data->code, &context->signature, handler, data);
+ ZEND_ASSERT(FFI_OK == rc);
+#else
+# error "Neither ffi_prep_closure() nor ffi_prep_closure_loc() available"
+#endif
context->data.list = realloc(context->data.list, ++context->data.count * sizeof(*context->data.list));
context->data.list[context->data.count-1] = data;
}
static inline void PSI_LibffiDataFree(PSI_LibffiData *data) {
+ psi_ffi_closure_free(data->closure);
free(data->arginfo);
- ffi_closure_free(data->closure);
free(data);
}
decl_arg *darg = data->impl->decl->args->args[i];
arg_ptr[i] = psi_do_let(darg);
- arg_prm[i] = darg->let->val->is_reference ? &arg_ptr[i] : arg_ptr[i];
+ arg_prm[i] = (darg->let->val && darg->let->val->is_reference)
+ ? &arg_ptr[i] : arg_ptr[i];
darg->let->ptr = arg_ptr[i];
}