X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Flibjit.c;h=fd68c5089af636202d537c2cf76b858a69939b1c;hp=5c4a7b9313c1f4cebcebc15234264ce666561c87;hb=7474b3e23338ea03bcd65551959e2582cc455f9f;hpb=4a49fe2f8eb21cdeabb06acec7a0395b6708d911 diff --git a/src/libjit.c b/src/libjit.c index 5c4a7b9..fd68c50 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -1,49 +1,19 @@ #include "php.h" +#include "php_psi.h" #include "libjit.h" -#include "parser_proc.h" -static void init(PSI_Context *C) -{ - C->opaque = jit_context_create(); -} - -static void dtor(PSI_Context *C) -{ - jit_context_destroy(C->opaque); -} - -typedef struct PSI_ClosureData { - void *context; - impl *impl; - jit_type_t signature; - zval return_value; -} PSI_ClosureData; - -static inline PSI_ClosureData *PSI_ClosureDataAlloc(void *context, impl *impl) { - PSI_ClosureData *data = malloc(sizeof(*data)); - - data->context = context; - data->impl = impl; - - return data; -} +#include -static inline size_t impl_num_min_args(impl *impl) { - size_t i, n = impl->func->args->count; - - for (i = 0; i < impl->func->args->count; ++i) { - if (impl->func->args->args[i]->def) { - --n; - } - } - return n; -} +static void psi_jit_handler(jit_type_t _sig, void *result, void **_args, void *_data); static inline jit_abi_t psi_jit_abi(const char *convention) { return jit_abi_cdecl; } static inline jit_type_t psi_jit_type(token_t t) { switch (t) { + default: + ZEND_ASSERT(0); + /* no break */ case PSI_T_VOID: return jit_type_void; case PSI_T_SINT8: @@ -76,8 +46,6 @@ static inline jit_type_t psi_jit_type(token_t t) { return jit_type_sys_float; case PSI_T_DOUBLE: return jit_type_sys_double; - default: - abort(); } } static inline jit_type_t psi_jit_decl_type(decl_type *type) { @@ -90,168 +58,183 @@ static inline jit_type_t psi_jit_decl_arg_type(decl_arg *darg) { return psi_jit_decl_type(darg->type); } } -static void handler(jit_type_t _sig, void *result, void **_args, void *_data) + +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_LibjitData { + PSI_LibjitContext *context; + impl *impl; + zend_internal_arg_info *arginfo; + void *closure; + jit_type_t signature; + jit_type_t params[1]; +} PSI_LibjitData; + +static inline PSI_LibjitData *PSI_LibjitDataAlloc(PSI_LibjitContext *context, impl *impl) { + size_t i, c = impl->decl->args->count; + PSI_LibjitData *data = malloc(sizeof(*data) + (c ? c-1 : c) * sizeof(jit_type_t)); + + data->context = context; + data->impl = impl; + data->arginfo = psi_internal_arginfo(impl); + for (i = 0; i < c; ++i) { + data->params[i] = psi_jit_decl_arg_type(impl->decl->args->args[i]); + } + + data->signature = jit_type_create_signature( + psi_jit_abi(data->impl->decl->abi->convention), + psi_jit_decl_arg_type(data->impl->decl->func), + data->params, + data->impl->decl->args->count, + 1); + data->closure = jit_closure_create(context->jit, context->signature, &psi_jit_handler, data); + + context->data.list = realloc(context->data.list, ++context->data.count * sizeof(*context->data.list)); + context->data.list[context->data.count-1] = data; + + return data; +} + +static inline void PSI_LibjitDataFree(PSI_LibjitData *data) { + free(data->arginfo); + jit_type_free(data->signature); + free(data); +} + +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) { + size_t i; + + for (i = 0; i < L->data.count; ++i) { + PSI_LibjitDataFree(L->data.list[i]); + } + if (L->data.list) { + free(L->data.list); + } + 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_handler(jit_type_t _sig, void *result, void **_args, void *_data) { - zend_execute_data *execute_data = *(zend_execute_data **)_args[0]; - zval *return_value = *(zval **)_args[1]; - PSI_ClosureData *data = _data; - impl_arg *iarg; + PSI_LibjitData *data = _data; size_t i; - void **arg_ptr = NULL, **arg_prm = NULL; - impl_val ret_val, *arg_val = NULL; - jit_type_t signature, *sig_prm; + void **arg_prm = NULL; + impl_val ret_val; - 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; - } - ZEND_PARSE_PARAMETERS_END(); + if (SUCCESS != psi_parse_args(*(zend_execute_data **)_args[0], data->impl)) { + return; + } if (data->impl->decl->args->count) { - arg_ptr = malloc(data->impl->decl->args->count * sizeof(*arg_ptr)); arg_prm = malloc(data->impl->decl->args->count * sizeof(*arg_prm)); - arg_val = malloc(data->impl->decl->args->count * sizeof(*arg_val)); - sig_prm = malloc(data->impl->decl->args->count * sizeof(*sig_prm)); for (i = 0; i < data->impl->decl->args->count; ++i) { decl_arg *darg = data->impl->decl->args->args[i]; - impl_arg *iarg = darg->let->arg; - - switch (darg->let->val->func->type) { - case PSI_T_BOOLVAL: - if (iarg->type->type == PSI_T_BOOL) { - arg_val[i].bval = iarg->val.bval; - } else { - arg_val[i].bval = zend_is_true(iarg->_zv); - } - break; - case PSI_T_INTVAL: - if (iarg->type->type == PSI_T_INT) { - arg_val[i].lval = iarg->val.lval; - } else { - arg_val[i].lval = zval_get_long(iarg->_zv); - } - break; - case PSI_T_STRVAL: - if (iarg->type->type == PSI_T_STRING) { - arg_val[i].str.val = estrndup(iarg->val.str.val, iarg->val.str.len); - } else { - zend_string *zs = zval_get_string(iarg->_zv); - arg_val[i].str.val = estrndup(zs->val, zs->len); - zend_string_release(zs); - } - break; - case PSI_T_STRLEN: - if (iarg->type->type == PSI_T_STRING) { - arg_val[i].lval =iarg->val.str.len; - } else { - zend_string *zs = zval_get_string(iarg->_zv); - arg_val[i].lval = zs->len; - zend_string_release(zs); - } - break; - } - arg_ptr[i] = &arg_val[i]; - arg_prm[i] = darg->let->val->is_reference ? &arg_ptr[i] : arg_ptr[i]; - sig_prm[i] = psi_jit_decl_arg_type(darg); + + arg_prm[i] = psi_do_let(darg); } } - signature = jit_type_create_signature( - psi_jit_abi(data->impl->decl->abi->convention), - psi_jit_decl_arg_type(data->impl->decl->func), - sig_prm, - data->impl->decl->args->count, - 1); - jit_apply(signature, data->impl->decl->dlptr, arg_prm, data->impl->decl->args->count, &ret_val); - - switch (data->impl->stmts->ret.list[0]->func->type) { - case PSI_T_TO_STRING: - if (data->impl->decl->func->var->pointer_level) { - switch (real_decl_type(data->impl->decl->func->type)->type) { - case PSI_T_CHAR: - case PSI_T_SINT8: - case PSI_T_UINT8: - RETVAL_STRING(ret_val.str.val); - break; - } + jit_apply(data->signature, data->impl->decl->dlptr, arg_prm, data->impl->decl->args->count, &ret_val); + + psi_do_return(data->impl, &ret_val, *(zval **)_args[1]); + + for (i = 0; i < data->impl->stmts->set.count; ++i) { + set_stmt *set = data->impl->stmts->set.list[i]; + + if (set->arg->_zv) { + psi_do_set(set->arg->_zv, set->val->func, set->val->vars); } - break; } + + for (i = 0; i < data->impl->stmts->fre.count; ++i) { + free_stmt *fre = data->impl->stmts->fre.list[i]; + + psi_do_free(fre); + } + + psi_do_clean(data->impl); + + if (arg_prm) { + free(arg_prm); + } +} + +static void psi_jit_init(PSI_Context *C) +{ + C->context = PSI_LibjitContextInit(NULL); +} + +static void psi_jit_dtor(PSI_Context *C) +{ + PSI_LibjitContextFree((void *) &C->context); } -static zend_function_entry *compile(PSI_Context *C, PSI_Data *D) +static zend_function_entry *psi_jit_compile(PSI_Context *C, PSI_Data *D) { size_t i, j = 0; - jit_type_t signature, params[] = { - jit_type_void_ptr, - jit_type_void_ptr - }; zend_function_entry *zfe = calloc(D->impls->count + 1, sizeof(*zfe)); + PSI_LibjitContext *ctx = C->context; - jit_context_build_start(C->opaque); + jit_context_build_start(ctx->jit); for (i = 0; i < D->impls->count; ++i) { - zend_function_entry *zf; - PSI_ClosureData *data; + zend_function_entry *zf = &zfe[j]; + PSI_LibjitData *data; if (!D->impls->list[i]->decl) { continue; } - zf = &zfe[j++]; - data = PSI_ClosureDataAlloc(C, D->impls->list[i]); - signature = jit_type_create_signature(jit_abi_cdecl, jit_type_void, params, 2, 1); + data = PSI_LibjitDataAlloc(ctx, D->impls->list[i]); zf->fname = D->impls->list[i]->func->name + (D->impls->list[i]->func->name[0] == '\\'); - zf->handler = jit_closure_create(C->opaque, signature, &handler, data); + zf->num_args = D->impls->list[i]->func->args->count; + zf->handler = data->closure; + zf->arg_info = data->arginfo; + ++j; } - jit_context_build_end(C->opaque); + jit_context_build_end(ctx->jit); return zfe; } static PSI_ContextOps ops = { - init, - dtor, - compile, + psi_jit_init, + psi_jit_dtor, + psi_jit_compile, }; PSI_ContextOps *PSI_Libjit(void)