- zend_execute_data *execute_data = *(zend_execute_data **)_args[0];
- zval *return_value = *(zval **)_args[1];
- PSI_ClosureData *data = _data;
- impl_arg *iarg;
- size_t i;
- void **arg_ptr = NULL, **arg_prm = NULL;
- impl_val ret_val, *arg_val = NULL;
- jit_type_t signature, *sig_prm;
-
- if (!data->impl->func->args->count) {
- if (SUCCESS != zend_parse_parameters_none()) {
- return;
- }
- } else
- ZEND_PARSE_PARAMETERS_START(impl_num_min_args(data->impl), data->impl->func->args->count)
- nextarg:
- iarg = data->impl->func->args->args[_i];
- if (iarg->def) {
- Z_PARAM_OPTIONAL;
- }
- if (PSI_T_BOOL == iarg->type->type) {
- if (iarg->def) {
- iarg->val.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0;
- }
- Z_PARAM_BOOL(iarg->val.bval);
- } else if (PSI_T_INT == iarg->type->type) {
- if (iarg->def) {
- iarg->val.lval = zend_atol(iarg->def->text, strlen(iarg->def->text));
- }
- Z_PARAM_LONG(iarg->val.lval);
- } else if (PSI_T_FLOAT == iarg->type->type) {
- if (iarg->def) {
- iarg->val.dval = zend_strtod(iarg->def->text, NULL);
- }
- Z_PARAM_DOUBLE(iarg->val.dval);
- } else if (PSI_T_STRING == iarg->type->type) {
- if (iarg->def) {
- /* FIXME */
- iarg->val.str.len = strlen(iarg->def->text) - 2;
- iarg->val.str.val = &iarg->def->text[1];
- }
- Z_PARAM_STRING(iarg->val.str.val, iarg->val.str.len);
- } else {
- error_code = ZPP_ERROR_FAILURE;
- break;
- }
- iarg->_zv = _arg;
- if (_i < _max_num_args) {
- goto nextarg;
+ jit_type_free(*typ_ptr);
+}
+
+static inline jit_abi_t psi_jit_abi(zend_string *convention)
+{
+ if (zend_string_equals_literal(convention, "stdcall")) {
+ return jit_abi_stdcall;
+ }
+ if (zend_string_equals_literal(convention, "fastcall")) {
+ return jit_abi_fastcall;
+ }
+ return jit_abi_cdecl;
+}
+
+static void psi_jit_handler(jit_type_t sig, void *result, void **args, void *data)
+{
+ struct psi_impl *impl = data;
+ struct psi_jit_impl_info *info = impl->info;
+
+ psi_context_call(info->context, *(zend_execute_data **)args[0], *(zval **) args[1], impl);
+}
+
+static void psi_jit_callback(jit_type_t sig, void *result, void **args, void *data)
+{
+ struct psi_jit_callback_info *cb_info = data;
+ struct psi_call_frame_callback cb_data;
+
+ assert(cb_info->impl_info->frame);
+
+ cb_data.cb = cb_info->let_exp;
+ cb_data.argc = jit_type_num_params(sig);
+ cb_data.argv = args;
+ cb_data.rval = result;
+
+ psi_call_frame_do_callback(cb_info->impl_info->frame, &cb_data);
+}
+
+static bool psi_jit_load(void)
+{
+#if HAVE_INT128
+ jit_type_t ll_fields[2], ull_fields[2];
+
+ ll_fields[0] = ll_fields[1] = jit_type_long;
+ jit_type_llong = jit_type_create_struct(ll_fields, 2, 1);
+
+ ull_fields[0] = ull_fields[1] = jit_type_ulong;
+ jit_type_ullong = jit_type_create_struct(ull_fields, 2, 1);
+#endif
+ return true;
+}
+
+static void psi_jit_free(void)
+{
+#if HAVE_INT128
+ jit_type_free(jit_type_llong);
+ jit_type_free(jit_type_ullong);
+#endif
+}
+
+static bool psi_jit_init(struct psi_context *C)
+{
+ struct psi_jit_context *context = pecalloc(1, sizeof(*context), 1);
+ jit_type_t params[] = {jit_type_void_ptr, jit_type_void_ptr};
+
+ context->jit = jit_context_create();
+ if (!context->jit) {
+ pefree(context, 1);
+ return false;
+ }
+
+ context->signature = jit_type_create_signature(jit_abi_fastcall, jit_type_void,
+ params, 2, 1);
+ if (!context->signature) {
+ jit_context_destroy(context->jit);
+ pefree(context, 1);
+ return false;
+ }
+
+ C->context = context;
+ return true;
+}
+
+static void psi_jit_dtor(struct psi_context *C)
+{
+ if (C->context) {
+ struct psi_jit_context *context = C->context;
+
+ jit_type_free(context->signature);
+ jit_context_destroy(context->jit);
+
+ pefree(C->context, 1);
+ C->context = NULL;
+ }
+}
+
+
+static bool psi_jit_composite_init(struct psi_context *C,
+ struct psi_decl_arg *darg)
+{
+ struct psi_jit_struct_info *info;
+
+ if (darg->engine.type) {
+ return true;
+ }
+
+ info = pecalloc(1, sizeof(*info), 1);
+ info->eles = psi_plist_init((psi_plist_dtor) psi_jit_type_free);
+ psi_context_composite_type_elements(C, darg, &info->eles);
+ info->strct = jit_type_create_struct((jit_type_t *)
+ psi_plist_eles(info->eles),
+ psi_plist_count(info->eles), 0);
+
+ darg->engine.info = info;
+ darg->engine.type = info->strct;
+
+ return true;
+}
+
+static void psi_jit_composite_dtor(struct psi_context *C,
+ struct psi_decl_arg *darg)
+{
+ struct psi_jit_struct_info *info = darg->engine.info;
+
+ if (info) {
+ darg->engine.info = NULL;
+ darg->engine.type = NULL;
+
+ jit_type_free(info->strct);
+ /* just free */
+ pefree(info->eles, 1);
+ pefree(info, 1);
+ }
+}
+
+static void psi_jit_extvar_get(jit_type_t sig, void *result, void **args, void *data)
+{
+ struct psi_decl_extvar *evar = data;
+
+ psi_decl_extvar_get(evar, result);
+}
+
+static void psi_jit_extvar_set(jit_type_t sig, void *result, void **args, void *data)
+{
+ struct psi_decl_extvar *evar = data;
+
+ psi_decl_extvar_set(evar, args[0]);
+}
+
+static bool psi_jit_decl_init(struct psi_context *, struct psi_decl *);
+
+static bool psi_jit_extvar_init(struct psi_context *C,
+ struct psi_decl_extvar *evar)
+{
+ struct psi_jit_context *ctx = C->context;
+ struct psi_jit_extvar_info *info = pecalloc(1, sizeof(*info), 1);
+
+ evar->info = info;
+
+ psi_jit_decl_init(C, evar->getter);
+ psi_jit_decl_init(C, evar->setter);
+
+ jit_context_build_start(ctx->jit);
+
+ info->get.signature = jit_type_create_signature(jit_abi_cdecl,
+ psi_context_decl_arg_call_type(C, evar->getter->func), NULL, 0, 1);
+ if (!info->get.signature) {
+ goto failure;
+ }
+ info->get.closure = jit_closure_create(ctx->jit, info->get.signature,
+ psi_jit_extvar_get, evar);
+ if (!info->get.closure) {
+ goto failure;
+ }
+
+ info->set.params[0] = psi_context_decl_arg_call_type(C, evar->arg);
+ info->set.signature = jit_type_create_signature(jit_abi_cdecl,
+ psi_context_decl_arg_call_type(C, evar->setter->func),
+ info->set.params, 1, 1);
+ if (!info->set.signature) {
+ goto failure;
+ }
+ info->set.closure = jit_closure_create(ctx->jit, info->set.signature,
+ psi_jit_extvar_set, evar);
+ if (!info->set.closure) {
+ goto failure;
+ }
+
+ evar->getter->sym = info->get.closure;
+ evar->setter->sym = info->set.closure;
+
+ jit_context_build_end(ctx->jit);
+ return true;
+failure: ;
+ jit_context_build_end(ctx->jit);
+ return false;
+}
+
+static void psi_jit_extvar_dtor(struct psi_context *C,
+ struct psi_decl_extvar *evar) {
+ if (evar->info) {
+ pefree(evar->info, 1);
+ evar->info = NULL;
+ }
+}
+
+static bool psi_jit_decl_init(struct psi_context *C, struct psi_decl *decl)
+{
+ if (!decl->info) {
+ struct psi_jit_context *ctx = C->context;
+ size_t i, c = psi_plist_count(decl->args);
+ struct psi_decl_arg *arg;
+ struct psi_jit_decl_info *info = pecalloc(1,
+ sizeof(*info) + 2 * c * sizeof(void *), 1);
+
+ decl->info = info;
+
+ jit_context_build_start(ctx->jit);
+
+ for (i = 0; psi_plist_get(decl->args, i, &arg); ++i) {
+ info->params[i] = psi_context_decl_arg_call_type(C, arg);