From 6a8a77b52b636041de54d1022016b4f2aa510c05 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 18 Nov 2015 18:15:10 +0100 Subject: [PATCH] refactor to psi_call --- php_psi.h | 7 +- {tests/stat => psis}/stat.psi | 0 psis/stdlib.psi | 2 + {tests/time => psis}/time.psi | 0 {tests/uname => psis}/uname.psi | 0 src/context.c | 34 ++++-- src/context.h | 4 +- src/libffi.c | 208 +++++++++++--------------------- src/libjit.c | 170 ++++++++++---------------- src/module.c | 58 +++++++-- src/parser.h | 9 +- tests/stat/stat001.phpt | 2 +- tests/time/time001.phpt | 2 +- tests/time/time002.phpt | 2 +- tests/time/time003.phpt | 2 +- tests/time/time004.phpt | 2 +- tests/uname/uname001.phpt | 2 +- 17 files changed, 222 insertions(+), 282 deletions(-) rename {tests/stat => psis}/stat.psi (100%) create mode 100644 psis/stdlib.psi rename {tests/time => psis}/time.psi (100%) rename {tests/uname => psis}/uname.psi (100%) diff --git a/php_psi.h b/php_psi.h index 9ebf8e7..b4b96e8 100644 --- a/php_psi.h +++ b/php_psi.h @@ -38,12 +38,7 @@ void psi_to_double(zval *return_value, token_t t, impl_val *ret_val, set_value * void psi_to_string(zval *return_value, token_t t, impl_val *ret_val, set_value *set, decl_var *var); void psi_to_array(zval *return_value, token_t t, impl_val *ret_val, set_value *set, decl_var *var); -ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl); -void *psi_do_let(decl_arg *darg); -void psi_do_set(zval *return_value, set_value *set); -void psi_do_return(zval *return_value, return_stmt *ret, impl_val *ret_val); -void psi_do_free(free_stmt *fre); -void psi_do_clean(impl *impl); +void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl); ZEND_BEGIN_MODULE_GLOBALS(psi) char *engine; diff --git a/tests/stat/stat.psi b/psis/stat.psi similarity index 100% rename from tests/stat/stat.psi rename to psis/stat.psi diff --git a/psis/stdlib.psi b/psis/stdlib.psi new file mode 100644 index 0000000..6044d41 --- /dev/null +++ b/psis/stdlib.psi @@ -0,0 +1,2 @@ + +extern void free(void *ptr); diff --git a/tests/time/time.psi b/psis/time.psi similarity index 100% rename from tests/time/time.psi rename to psis/time.psi diff --git a/tests/uname/uname.psi b/psis/uname.psi similarity index 100% rename from tests/uname/uname.psi rename to psis/uname.psi diff --git a/src/context.c b/src/context.c index e499c5f..987fb9a 100644 --- a/src/context.c +++ b/src/context.c @@ -235,19 +235,19 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ #ifndef RTLD_NEXT # define RTLD_NEXT ((void *) -1l) #endif - decl->dlptr = dlsym(dl ?: RTLD_NEXT, func->var->name); - if (!decl->dlptr) { + decl->call.sym = dlsym(dl ?: RTLD_NEXT, func->var->name); + if (!decl->call.sym) { size_t i; for (i = 0; i < psi_predef_func_count(); ++i) { psi_predef_func *pre = &psi_predef_funcs[i]; if (!strcmp(func->var->name, pre->name)) { - decl->dlptr = pre->func; + decl->call.sym = pre->func; break; } } - if (!decl->dlptr) { + if (!decl->call.sym) { data->error(PSI_WARNING, "Failed to locate symbol '%s': %s", func->var->name, dlerror()); } @@ -368,10 +368,13 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { impl->func->name); return 0; } + if (!validate_set_value(data, ret->set, ret->decl)) { return 0; } + impl->decl->impl = impl; + return 1; } static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { @@ -576,7 +579,13 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr C->error = error; C->ops = ops; - ops->init(C); + + if (ops->init) { + ops->init(C); + } + + ZEND_ASSERT(ops->call != NULL); + ZEND_ASSERT(ops->compile != NULL); /* build up predefs in a temporary PSI_Data for validation */ memset(&T, 0, sizeof(T)); @@ -818,29 +827,34 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C) } } - return C->closures = C->ops->compile(C); } -void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args) +void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl) { - C->ops->call(C, ret_val, decl, args); + C->ops->call(C, ret_val, decl); } void PSI_ContextDtor(PSI_Context *C) { size_t i; + zend_function_entry *zfe; - C->ops->dtor(C); + if (C->ops->dtor) { + C->ops->dtor(C); + } free_decl_libs(&C->psi.libs); for (i = 0; i < C->count; ++i) { PSI_DataDtor(&C->data[i]); } - free(C->data); + + for (zfe = C->closures; zfe->fname; ++zfe) { + free((void *) zfe->arg_info); + } free(C->closures); if (C->consts) { diff --git a/src/context.h b/src/context.h index 77db31a..4f86444 100644 --- a/src/context.h +++ b/src/context.h @@ -14,7 +14,7 @@ struct PSI_ContextOps { void (*init)(PSI_Context *C); void (*dtor)(PSI_Context *C); zend_function_entry *(*compile)(PSI_Context *C); - void (*call)(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args); + void (*call)(PSI_Context *C, impl_val *ret_val, decl *decl); }; struct PSI_Context { @@ -30,7 +30,7 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr void PSI_ContextBuild(PSI_Context *C, const char *path); int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P); zend_function_entry *PSI_ContextCompile(PSI_Context *C); -void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args); +void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl); void PSI_ContextDtor(PSI_Context *C); void PSI_ContextFree(PSI_Context **C); diff --git a/src/libffi.c b/src/libffi.c index f1d7282..d802bd1 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -53,7 +53,7 @@ static void psi_ffi_handler(ffi_cif *signature, void *_result, void **_args, voi static inline ffi_abi psi_ffi_abi(const char *convention) { return FFI_DEFAULT_ABI; } -static inline ffi_type *psi_ffi_type(token_t t) { +static inline ffi_type *psi_ffi_token_type(token_t t) { switch (t) { default: ZEND_ASSERT(0); @@ -87,7 +87,7 @@ static inline ffi_type *psi_ffi_type(token_t t) { } } static inline ffi_type *psi_ffi_decl_type(decl_type *type) { - return psi_ffi_type(real_decl_type(type)->type); + return psi_ffi_token_type(real_decl_type(type)->type); } static inline ffi_type *psi_ffi_decl_arg_type(decl_arg *darg) { if (darg->var->pointer_level) { @@ -100,70 +100,63 @@ static inline ffi_type *psi_ffi_decl_arg_type(decl_arg *darg) { typedef struct PSI_LibffiContext { ffi_cif signature; ffi_type *params[2]; - struct { - struct PSI_LibffiData **list; - size_t count; - } data; } PSI_LibffiContext; -typedef struct PSI_LibffiData { - PSI_LibffiContext *context; - impl *impl; - zend_internal_arg_info *arginfo; +typedef struct PSI_LibffiCall { void *code; ffi_closure *closure; ffi_cif signature; - ffi_type *params[1]; -} PSI_LibffiData; + void *params[1]; /* [type1, type2, NULL, arg1, arg2] ... */ +} PSI_LibffiCall; -static inline PSI_LibffiData *PSI_LibffiDataAlloc(PSI_LibffiContext *context, impl *impl) { - ffi_status rc; - size_t i, c = impl->decl->args ? impl->decl->args->count : 0; - PSI_LibffiData *data = malloc(sizeof(*data) + c * sizeof(ffi_type *)); +static inline PSI_LibffiCall *PSI_LibffiCallAlloc(PSI_Context *C, decl *decl) { + int rc; + size_t i, c = decl->args ? decl->args->count : 0; + PSI_LibffiCall *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *)); - data->context = context; - data->impl = impl; - data->arginfo = psi_internal_arginfo(impl); for (i = 0; i < c; ++i) { - data->params[i] = psi_ffi_decl_arg_type(impl->decl->args->args[i]); + call->params[i] = psi_ffi_decl_arg_type(decl->args->args[i]); } - data->params[c] = NULL; - - rc = ffi_prep_cif( - &data->signature, - psi_ffi_abi(data->impl->decl->abi->convention), - c, - psi_ffi_decl_arg_type(data->impl->decl->func), - data->params); + call->params[c] = NULL; + + decl->call.info = call; + decl->call.args = (void **) &call->params[c+1]; + + rc = ffi_prep_cif(&call->signature, psi_ffi_abi(decl->abi->convention), + c, psi_ffi_decl_arg_type(decl->func), (ffi_type **) call->params); ZEND_ASSERT(FFI_OK == rc); - data->closure = psi_ffi_closure_alloc(sizeof(ffi_closure), &data->code); - ZEND_ASSERT(data->closure != NULL); + return call; +} + +static inline void PSI_LibffiCallInitClosure(PSI_Context *C, PSI_LibffiCall *call, impl *impl) { + PSI_LibffiContext *context = C->context; + int rc; + + call->closure = psi_ffi_closure_alloc(sizeof(ffi_closure), &call->code); + ZEND_ASSERT(call->closure != NULL); + #if PSI_HAVE_FFI_PREP_CLOSURE_LOC rc = ffi_prep_closure_loc( - data->closure, + call->closure, &context->signature, psi_ffi_handler, - data, - data->code); - ZEND_ASSERT(FFI_OK == rc); + impl, + call->code); + #elif PSI_HAVE_FFI_PREP_CLOSURE rc = ffi_prep_closure(data->code, &context->signature, psi_ffi_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; - - return data; + ZEND_ASSERT(FFI_OK == rc); } -static inline void PSI_LibffiDataFree(PSI_LibffiData *data) { - psi_ffi_closure_free(data->closure); - free(data->arginfo); - free(data); +static inline void PSI_LibffiCallFree(PSI_LibffiCall *call) { + if (call->closure) { + psi_ffi_closure_free(call->closure); + } + free(call); } static inline PSI_LibffiContext *PSI_LibffiContextInit(PSI_LibffiContext *L) { @@ -182,69 +175,9 @@ static inline PSI_LibffiContext *PSI_LibffiContextInit(PSI_LibffiContext *L) { return L; } -static inline void PSI_LibffiContextDtor(PSI_LibffiContext *L) { - size_t i; - - for (i = 0; i < L->data.count; ++i) { - PSI_LibffiDataFree(L->data.list[i]); - } - if (L->data.list) { - free(L->data.list); - } -} - -static inline void PSI_LibffiContextFree(PSI_LibffiContext **L) { - if (*L) { - PSI_LibffiContextDtor(*L); - free(*L); - *L = NULL; - } -} - static void psi_ffi_handler(ffi_cif *_sig, void *_result, void **_args, void *_data) { - PSI_LibffiData *data = _data; - size_t i; - void **arg_prm = NULL; - impl_val ret_val; - - if (SUCCESS != psi_parse_args(*(zend_execute_data **)_args[0], data->impl)) { - return; - } - - if (data->impl->decl->args) { - arg_prm = malloc(data->impl->decl->args->count * sizeof(*arg_prm)); - - for (i = 0; i < data->impl->decl->args->count; ++i) { - decl_arg *darg = data->impl->decl->args->args[i]; - - arg_prm[i] = psi_do_let(darg); - } - } - - ffi_call(&data->signature, FFI_FN(data->impl->decl->dlptr), &ret_val, arg_prm); - - psi_do_return(*(zval **)_args[1], data->impl->stmts->ret.list[0], &ret_val); - - 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); - } - } - - 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); - } + psi_call(*(zend_execute_data **)_args[0], *(zval **)_args[1], _data); } static void psi_ffi_init(PSI_Context *C) @@ -252,16 +185,23 @@ static void psi_ffi_init(PSI_Context *C) C->context = PSI_LibffiContextInit(NULL); } -static void psi_ffi_dtor(PSI_Context *C) -{ - PSI_LibffiContextFree((void *) &C->context); +static void psi_ffi_dtor(PSI_Context *C) { + size_t i; + + for (i = 0; i < C->decls->count; ++i) { + decl *decl = C->decls->list[i]; + + if (decl->call.info) { + PSI_LibffiCallFree(decl->call.info); + } + } + free(C->context); } static zend_function_entry *psi_ffi_compile(PSI_Context *C) { size_t i, j = 0; zend_function_entry *zfe; - PSI_LibffiContext *ctx = C->context; if (!C->impls) { return NULL; @@ -270,46 +210,40 @@ static zend_function_entry *psi_ffi_compile(PSI_Context *C) zfe = calloc(C->impls->count + 1, sizeof(*zfe)); for (i = 0; i < C->impls->count; ++i) { zend_function_entry *zf = &zfe[j]; - PSI_LibffiData *data; + PSI_LibffiCall *call; + impl *impl = C->impls->list[i]; - if (!C->impls->list[i]->decl) { + if (!impl->decl) { continue; } - data = PSI_LibffiDataAlloc(ctx, C->impls->list[i]); - zf->fname = C->impls->list[i]->func->name + (C->impls->list[i]->func->name[0] == '\\'); - zf->num_args = C->impls->list[i]->func->args->count; - zf->handler = data->code; - zf->arg_info = data->arginfo; + call = PSI_LibffiCallAlloc(C, impl->decl); + PSI_LibffiCallInitClosure(C, call, impl); + + zf->fname = impl->func->name + (impl->func->name[0] == '\\'); + zf->num_args = impl->func->args->count; + zf->handler = call->code; + zf->arg_info = psi_internal_arginfo(impl); ++j; } - return zfe; -} + for (i = 0; i < C->decls->count; ++i) { + decl *decl = C->decls->list[i]; -static void psi_ffi_call(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args) { - ffi_cif signature; - ffi_type **types; - void **argps; - size_t i; - - /* FIXME: cache in decl */ - - types = calloc(decl->args->count + 1, sizeof(*types)); - argps = calloc(decl->args->count + 1, sizeof(*argps)); - for (i = 0; i < decl->args->count; ++i) { - decl_arg *darg = decl->args->args[i]; + if (decl->impl) { + continue; + } - types[i] = psi_ffi_decl_arg_type(darg); - argps[i] = args[i]; + PSI_LibffiCallAlloc(C, decl); } - ffi_prep_cif(&signature, psi_ffi_abi(decl->abi->convention), decl->args->count, - psi_ffi_decl_arg_type(decl->func), types); - ffi_call(&signature, FFI_FN(decl->dlptr), ret_val, argps); + return zfe; +} + +static void psi_ffi_call(PSI_Context *C, impl_val *ret_val, decl *decl) { + PSI_LibffiCall *call = decl->call.info; - free(types); - free(argps); + ffi_call(&call->signature, FFI_FN(decl->call.sym), ret_val, decl->call.args); } static PSI_ContextOps ops = { diff --git a/src/libjit.c b/src/libjit.c index e1d6cf8..4866809 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -9,7 +9,7 @@ static void psi_jit_handler(jit_type_t _sig, void *result, void **_args, void *_ 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) { +static inline jit_type_t psi_jit_token_type(token_t t) { switch (t) { default: ZEND_ASSERT(0); @@ -43,7 +43,7 @@ static inline jit_type_t psi_jit_type(token_t t) { } } static inline jit_type_t psi_jit_decl_type(decl_type *type) { - return psi_jit_type(real_decl_type(type)->type); + return psi_jit_token_type(real_decl_type(type)->type); } static inline jit_type_t psi_jit_decl_arg_type(decl_arg *darg) { if (darg->var->pointer_level) { @@ -62,44 +62,45 @@ typedef struct PSI_LibjitContext { } data; } PSI_LibjitContext; +typedef struct PSI_LibjitCall { + void *closure; + jit_type_t signature; + jit_type_t params[1]; /* [type1, type2, NULL, arg1, arg2] ... */ +} PSI_LibjitCall; + 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)); +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 *)); - 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]); + call->params[i] = psi_jit_decl_arg_type(decl->args->args[i]); } + call->params[c] = NULL; - 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); + decl->call.info = call; + decl->call.args = (void **) &call->params[c+1]; - context->data.list = realloc(context->data.list, ++context->data.count * sizeof(*context->data.list)); - context->data.list[context->data.count-1] = data; + call->signature = jit_type_create_signature( + psi_jit_abi(decl->abi->convention), + psi_jit_decl_arg_type(decl->func), + call->params, c, 1); + return call; +} - return data; +static inline void PSI_LibjitCallInitClosure(PSI_Context *C, PSI_LibjitCall *call, impl *impl) { + PSI_LibjitContext *context = C->context; + call->closure = jit_closure_create(context->jit, context->signature, + &psi_jit_handler, impl); } -static inline void PSI_LibjitDataFree(PSI_LibjitData *data) { - free(data->arginfo); - jit_type_free(data->signature); - free(data); +static inline void PSI_LibjitCallFree(PSI_LibjitCall *call) { + jit_type_free(call->signature); } static inline PSI_LibjitContext *PSI_LibjitContextInit(PSI_LibjitContext *L) { @@ -114,20 +115,13 @@ static inline PSI_LibjitContext *PSI_LibjitContextInit(PSI_LibjitContext *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); + 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); } @@ -142,48 +136,7 @@ static inline void PSI_LibjitContextFree(PSI_LibjitContext **L) { static void psi_jit_handler(jit_type_t _sig, void *result, void **_args, void *_data) { - PSI_LibjitData *data = _data; - size_t i; - void **arg_prm = NULL; - impl_val ret_val; - - if (SUCCESS != psi_parse_args(*(zend_execute_data **)_args[0], data->impl)) { - return; - } - - if (data->impl->decl->args->count) { - arg_prm = malloc(data->impl->decl->args->count * sizeof(*arg_prm)); - - for (i = 0; i < data->impl->decl->args->count; ++i) { - decl_arg *darg = data->impl->decl->args->args[i]; - - arg_prm[i] = psi_do_let(darg); - } - } - - jit_apply(data->signature, data->impl->decl->dlptr, arg_prm, data->impl->decl->args->count, &ret_val); - - psi_do_return(*(zval **)_args[1], data->impl->stmts->ret.list[0], &ret_val); - - 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); - } - } - - 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); - } + psi_call(*(zend_execute_data **)_args[0], *(zval **)_args[1], _data); } static void psi_jit_init(PSI_Context *C) @@ -193,6 +146,13 @@ static void psi_jit_init(PSI_Context *C) static void psi_jit_dtor(PSI_Context *C) { + size_t i; + + for (i = 0; i < C->decls->count; ++i) { + decl *decl = C->decls->list[i]; + + PSI_LibjitCallFree(decl->call.info); + } PSI_LibjitContextFree((void *) &C->context); } @@ -211,51 +171,43 @@ static zend_function_entry *psi_jit_compile(PSI_Context *C) for (i = 0; i < C->impls->count; ++i) { zend_function_entry *zf = &zfe[j]; - PSI_LibjitData *data; + PSI_LibjitCall *call; + impl *impl = C->impls->list[i]; - if (!C->impls->list[i]->decl) { + if (!impl->decl) { continue; } - data = PSI_LibjitDataAlloc(ctx, C->impls->list[i]); - zf->fname = C->impls->list[i]->func->name + (C->impls->list[i]->func->name[0] == '\\'); - zf->num_args = C->impls->list[i]->func->args->count; - zf->handler = data->closure; - zf->arg_info = data->arginfo; + call = PSI_LibjitCallAlloc(C, impl->decl); + PSI_LibjitCallInitClosure(C, call, impl); + + zf->fname = impl->func->name + (impl->func->name[0] == '\\'); + zf->num_args = impl->func->args->count; + zf->handler = call->closure; + zf->arg_info = psi_internal_arginfo(impl); ++j; } - jit_context_build_end(ctx->jit); - - return zfe; -} - -static void psi_jit_call(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args) { - jit_type_t signature, *types; - void **argps; - size_t i; + for (i = 0; i < C->decls->count; ++i) { + decl *decl = C->decls->list[i]; - /* FIXME: cache in decl */ - - types = calloc(decl->args->count + 1, sizeof(*types)); - argps = calloc(decl->args->count + 1, sizeof(*argps)); - for (i = 0; i < decl->args->count; ++i) { - decl_arg *darg = decl->args->args[i]; + if (decl->impl) { + continue; + } - types[i] = psi_jit_decl_arg_type(darg); - argps[i] = args[i]; + PSI_LibjitCallAlloc(C, decl); } - signature = jit_type_create_signature( - psi_jit_abi(decl->abi->convention), - psi_jit_decl_arg_type(decl->func), - types, decl->args->count, 1); - jit_apply(signature, decl->dlptr, argps, decl->args->count, ret_val); + jit_context_build_end(ctx->jit); + + return zfe; +} - jit_type_free(signature); - free(types); - free(argps); +static void psi_jit_call(PSI_Context *C, impl_val *ret_val, decl *decl) { + PSI_LibjitCall *call = decl->call.info; + jit_apply(call->signature, decl->call.sym, decl->call.args, + decl->args->count, ret_val); } static PSI_ContextOps ops = { diff --git a/src/module.c b/src/module.c index 811d4e4..8ab22ae 100644 --- a/src/module.c +++ b/src/module.c @@ -439,7 +439,7 @@ void psi_to_array(zval *return_value, token_t t, impl_val *ret_val, set_value *s } } -ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) +static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) { impl_arg *iarg; @@ -497,7 +497,7 @@ ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) return SUCCESS; } -void *psi_do_calloc(let_calloc *alloc) +static inline void *psi_do_calloc(let_calloc *alloc) { decl_type *type = real_decl_type(alloc->type); size_t size; @@ -512,7 +512,7 @@ void *psi_do_calloc(let_calloc *alloc) return ecalloc(alloc->n, size); } -void *psi_do_let(decl_arg *darg) +static inline void *psi_do_let(decl_arg *darg) { impl_arg *iarg = darg->let->arg; impl_val *arg_val; @@ -596,7 +596,7 @@ void *psi_do_let(decl_arg *darg) } } -void psi_do_set(zval *return_value, set_value *set) +static inline void psi_do_set(zval *return_value, set_value *set) { impl_val *val = (impl_val *) &set->vars->vars[0]->arg->let->ptr; token_t t = real_decl_type(set->vars->vars[0]->arg->type)->type; @@ -607,17 +607,17 @@ void psi_do_set(zval *return_value, set_value *set) set->func->handler(return_value, t, val, set, set->vars->vars[0]); } -void psi_do_return(zval *return_value, return_stmt *ret, impl_val *ret_val) +static inline void psi_do_return(zval *return_value, return_stmt *ret, impl_val *ret_val) { token_t t = real_decl_type(ret->decl->type)->type; ret->set->func->handler(return_value, t, ret_val, ret->set, ret->decl->var); } -void psi_do_free(free_stmt *fre) +static inline void psi_do_free(free_stmt *fre) { size_t i, j; - impl_val dummy, *argps[0x20]; + impl_val dummy; for (i = 0; i < fre->calls->count; ++i) { free_call *f = fre->calls->list[i]; @@ -626,14 +626,14 @@ void psi_do_free(free_stmt *fre) decl_var *dvar = f->vars->vars[j]; decl_arg *darg = dvar->arg; - argps[j] = &darg->let->out; + f->decl->call.args[j] = &darg->let->out; } - PSI_ContextCall(&PSI_G(context), &dummy, f->decl, argps); + PSI_ContextCall(&PSI_G(context), &dummy, f->decl); } } -void psi_do_clean(impl *impl) +static inline void psi_do_clean(impl *impl) { size_t i; @@ -668,6 +668,44 @@ void psi_do_clean(impl *impl) } } +void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) +{ + impl_val ret_val; + size_t i; + + if (SUCCESS != psi_parse_args(execute_data, impl)) { + return; + } + + if (impl->decl->args) { + for (i = 0; i < impl->decl->args->count; ++i) { + decl_arg *darg = impl->decl->args->args[i]; + + impl->decl->call.args[i] = psi_do_let(darg); + } + } + + PSI_ContextCall(&PSI_G(context), &ret_val, impl->decl); + + psi_do_return(return_value, impl->stmts->ret.list[0], &ret_val); + + for (i = 0; i < impl->stmts->set.count; ++i) { + set_stmt *set = impl->stmts->set.list[i]; + + if (set->arg->_zv) { + psi_do_set(set->arg->_zv, set->val); + } + } + + for (i = 0; i < impl->stmts->fre.count; ++i) { + free_stmt *fre = impl->stmts->fre.list[i]; + + psi_do_free(fre); + } + + psi_do_clean(impl); +} + PHP_MINIT_FUNCTION(psi) { PSI_ContextOps *ops; diff --git a/src/parser.h b/src/parser.h index 67252e2..d8955e5 100644 --- a/src/parser.h +++ b/src/parser.h @@ -234,7 +234,12 @@ typedef struct decl { decl_abi *abi; decl_arg *func; decl_args *args; - void *dlptr; + struct impl *impl; + struct { + void *sym; + void *info; + void **args; + } call; } decl; static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) { @@ -359,7 +364,7 @@ static inline impl_val *enref_impl_val(void *ptr, decl_var *var) { if (!var->pointer_level && real_decl_type(var->arg->type)->type != PSI_T_STRUCT) { return ptr; } - val = val_ptr = calloc(var->pointer_level, sizeof(void *)); + val = val_ptr = calloc(var->pointer_level + 1, sizeof(void *)); for (i = 1; i < var->pointer_level; ++i) { val_ptr->ptr = (void **) val_ptr + 1; val_ptr = val_ptr->ptr; diff --git a/tests/stat/stat001.phpt b/tests/stat/stat001.phpt index c4b4b96..3b180f9 100644 --- a/tests/stat/stat001.phpt +++ b/tests/stat/stat001.phpt @@ -1,7 +1,7 @@ --TEST-- stat --INI-- -psi.directory={PWD} +psi.directory={PWD}/../../psis:{PWD} --SKIPIF--