flush
authorMichael Wallner <mike@php.net>
Fri, 16 Oct 2015 11:27:44 +0000 (13:27 +0200)
committerMichael Wallner <mike@php.net>
Fri, 16 Oct 2015 11:27:44 +0000 (13:27 +0200)
php_psi.h
src/compiler.c
src/context.c [new file with mode: 0644]
src/context.h [new file with mode: 0644]
src/libjit.c [new file with mode: 0644]
src/libjit.h [new file with mode: 0644]
src/module.c

index 0828ebeb06746e56743cad39531ee998790d8e16..4be402729382bf8be7b713fce16a0060db7347ae 100644 (file)
--- a/php_psi.h
+++ b/php_psi.h
@@ -21,7 +21,7 @@ extern zend_module_entry psi_module_entry;
 
 ZEND_BEGIN_MODULE_GLOBALS(psi)
        char *directory;
 
 ZEND_BEGIN_MODULE_GLOBALS(psi)
        char *directory;
-       void *context;
+       PSI_Context context;
 ZEND_END_MODULE_GLOBALS(psi);
 
 #define PSI_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(psi, v)
 ZEND_END_MODULE_GLOBALS(psi);
 
 #define PSI_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(psi, v)
index f2821ca5cc78ff4aed4a580b40dbf92edc62b054..3181aeaa25e56ca9c2be405b3f2ce1e7282dfd35 100644 (file)
@@ -35,234 +35,7 @@ void PSI_Compiler_Free(PSI_Compiler **C)
        }
 }
 
        }
 }
 
-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;
-}
-
-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 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) {
-       case PSI_T_VOID:
-               return jit_type_void;
-       case PSI_T_SINT8:
-               return jit_type_sbyte;
-       case PSI_T_UINT8:
-               return jit_type_ubyte;
-       case PSI_T_SINT16:
-               return jit_type_short;
-       case PSI_T_UINT16:
-               return jit_type_ushort;
-       case PSI_T_SINT32:
-               return jit_type_int;
-       case PSI_T_UINT32:
-               return jit_type_uint;
-       case PSI_T_SINT64:
-               return jit_type_long;
-       case PSI_T_UINT64:
-               return jit_type_ulong;
-       case PSI_T_BOOL:
-               return jit_type_sys_bool;
-       case PSI_T_CHAR:
-               return jit_type_sys_char;
-       case PSI_T_SHORT:
-               return jit_type_sys_short;
-       case PSI_T_INT:
-               return jit_type_sys_int;
-       case PSI_T_LONG:
-               return jit_type_sys_long;
-       case PSI_T_FLOAT:
-               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) {
-       return psi_jit_type(real_decl_type(type)->type);
-}
-static inline jit_type_t psi_jit_decl_arg_type(decl_arg *darg) {
-       if (darg->var->pointer_level) {
-               return jit_type_void_ptr;
-       } else {
-               return psi_jit_decl_type(darg->type);
-       }
-}
-static void psi_jit_closure_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;
-       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;
-               }
-       ZEND_PARSE_PARAMETERS_END();
-
-       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);
-               }
-       }
-
-       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;
-                       }
-               }
-               break;
-       }
-}
 
 zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C)
 {
 
 zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C)
 {
-       size_t i, j = 0;
-       jit_type_t signature, params[] = {
-               jit_type_void_ptr,
-               jit_type_void_ptr
-       };
-       zend_function_entry *zfe = calloc(C->impls->count + 1, sizeof(*zfe));
-
-       for (i = 0; i < C->impls->count; ++i) {
-               zend_function_entry *zf;
-               PSI_ClosureData *data;
-
-               if (!C->impls->list[i]->decl) {
-                       continue;
-               }
-
-               zf = &zfe[j++];
-               data = PSI_ClosureDataAlloc(C->context, C->impls->list[i]);
-               signature = jit_type_create_signature(jit_abi_vararg, jit_type_void, params, 2, 1);
-               zf->fname = C->impls->list[i]->func->name + (C->impls->list[i]->func->name[0] == '\\');
-               zf->handler = jit_closure_create(C->context, signature, &psi_jit_closure_handler, data);
-       }
-
-       return zfe;
 }
 }
diff --git a/src/context.c b/src/context.c
new file mode 100644 (file)
index 0000000..2b91f43
--- /dev/null
@@ -0,0 +1,125 @@
+#include <sys/param.h>
+#include <dirent.h>
+#include <fnmatch.h>
+#include <errno.h>
+
+#include "php.h"
+#include "php_scandir.h"
+#include "context.h"
+
+PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error)
+{
+       if (!C) {
+               C = malloc(sizeof(*C));
+       }
+       memset(C, 0, sizeof(*C));
+
+       C->error = error;
+       C->ops = ops;
+       ops->init(C);
+
+       return C;
+}
+
+static int psi_select_dirent(const struct dirent *entry)
+{
+#ifndef FNM_CASEFOLD
+#define FNM_CASEFOLD 0
+#endif
+       return 0 == fnmatch("*.psi", entry->d_name, FNM_CASEFOLD);
+}
+
+
+void PSI_ContextBuild(PSI_Context *C, const char *path)
+{
+       int i, n;
+       struct dirent **entries = NULL;
+
+       n = php_scandir(path, &entries, psi_select_dirent, alphasort);
+
+       if (n < 0) {
+               C->error(PSI_WARNING, "Failed to scan PSI directory '%s'", path);
+       } else for (i = 0; i < n; ++i) {
+               char psi[MAXPATHLEN];
+               PSI_Parser P;
+               PSI_Validator V;
+
+               if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", path, entries[i]->d_name)) {
+                       C->error(PSI_WARNING, "Path to PSI file too long: %s/%s",
+                               path, entries[i]->d_name);
+               }
+               if (!PSI_ParserInit(&P, psi, psi_error, 0)) {
+                       C->error(PSI_WARNING, "Failed to init PSI parser (%s): %s",
+                               psi, strerror(errno));
+                       continue;
+               }
+
+               while (-1 != PSI_ParserScan(&P)) {
+                       PSI_ParserParse(&P, PSI_TokenAlloc(&P));
+               };
+               PSI_ParserParse(&P, NULL);
+
+               if (!PSI_ValidatorInit(&V, &P)) {
+                       C->error(PSI_WARNING, "Failed to init PSI validator");
+                       break;
+               }
+               PSI_ParserDtor(&P);
+
+               if (PSI_ValidatorValidate(&V)) {
+                       zend_function_entry *closures = PSI_ContextCompile(C, (PSI_Data *) &V);
+
+                       if (closures && SUCCESS != zend_register_functions(NULL, closures, NULL, MODULE_PERSISTENT)) {
+                               C->error(PSI_WARNING, "Failed to register functions!");
+                       }
+
+               }
+               PSI_ValidatorDtor(&V);
+       }
+       if (entries) {
+               for (i = 0; i < n; ++i) {
+                       free(entries[i]);
+               }
+               free(entries);
+       }
+
+}
+
+zend_function_entry *PSI_ContextCompile(PSI_Context *C, PSI_Data *D)
+{
+       size_t count = C->count++;
+       zend_function_entry *zfe;
+
+       C->data = realloc(C->data, C->count * sizeof(*C->data));
+       PSI_DataExchange(&C->data[count], D);
+
+       zfe = C->ops->compile(C, &C->data[count]);
+
+       C->closures = realloc(C->closures, C->count * sizeof(*C->closures));
+       C->closures[count] = zfe;
+
+       return zfe;
+}
+
+void PSI_ContextDtor(PSI_Context *C)
+{
+       size_t i;
+
+       C->ops->dtor(C);
+
+       for (i = 0; i < C->count; ++i) {
+               PSI_DataDtor(&C->data[i]);
+       }
+       free(C->data);
+
+       memset(C, 0, sizeof(*C));
+}
+
+void PSI_ContextFree(PSI_Context **C)
+{
+       if (*C) {
+               PSI_ContextDtor(*C);
+               free(*C);
+               *C = NULL;
+       }
+}
+
diff --git a/src/context.h b/src/context.h
new file mode 100644 (file)
index 0000000..d75c19e
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _PSI_CONTEXT_H
+#define _PSI_CONTEXT_H
+
+#define PSI_ERROR 16
+#define PSI_WARNING 32
+typedef void (*PSI_ContextErrorFunc)(int type, const char *msg, ...);
+
+typedef struct PSI_ContextOps {
+       void (*init)(struct PSI_Context *C);
+       void (*dtor)(struct PSI_Context *C);
+       zend_function_entry *(*compile)(struct PSI_Context *C, struct PSI_Data *D);
+} PSI_ContextOps;
+
+typedef struct PSI_Context {
+       void *opaque;
+       PSI_ContextErrorFunc error;
+       struct PSI_ContextOps *ops;
+       struct PSI_Data *data;
+       zend_function_entry **closures;
+       size_t count;
+} PSI_Context;
+
+PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error);
+void PSI_ContextBuild(PSI_Context *C, const char *path);
+zend_function_entry *PSI_ContextCompile(PSI_Context *C, PSI_Data *D);
+void PSI_ContextDtor(PSI_Context *C);
+void PSI_ContextFree(PSI_Context **C);
+
+#endif
diff --git a/src/libjit.c b/src/libjit.c
new file mode 100644 (file)
index 0000000..5c4a7b9
--- /dev/null
@@ -0,0 +1,260 @@
+#include "php.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;
+}
+
+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 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) {
+       case PSI_T_VOID:
+               return jit_type_void;
+       case PSI_T_SINT8:
+               return jit_type_sbyte;
+       case PSI_T_UINT8:
+               return jit_type_ubyte;
+       case PSI_T_SINT16:
+               return jit_type_short;
+       case PSI_T_UINT16:
+               return jit_type_ushort;
+       case PSI_T_SINT32:
+               return jit_type_int;
+       case PSI_T_UINT32:
+               return jit_type_uint;
+       case PSI_T_SINT64:
+               return jit_type_long;
+       case PSI_T_UINT64:
+               return jit_type_ulong;
+       case PSI_T_BOOL:
+               return jit_type_sys_bool;
+       case PSI_T_CHAR:
+               return jit_type_sys_char;
+       case PSI_T_SHORT:
+               return jit_type_sys_short;
+       case PSI_T_INT:
+               return jit_type_sys_int;
+       case PSI_T_LONG:
+               return jit_type_sys_long;
+       case PSI_T_FLOAT:
+               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) {
+       return psi_jit_type(real_decl_type(type)->type);
+}
+static inline jit_type_t psi_jit_decl_arg_type(decl_arg *darg) {
+       if (darg->var->pointer_level) {
+               return jit_type_void_ptr;
+       } else {
+               return psi_jit_decl_type(darg->type);
+       }
+}
+static void 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;
+       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;
+               }
+       ZEND_PARSE_PARAMETERS_END();
+
+       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);
+               }
+       }
+
+       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;
+                       }
+               }
+               break;
+       }
+}
+
+static zend_function_entry *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));
+
+       jit_context_build_start(C->opaque);
+
+       for (i = 0; i < D->impls->count; ++i) {
+               zend_function_entry *zf;
+               PSI_ClosureData *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);
+               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);
+       }
+
+       jit_context_build_end(C->opaque);
+
+       return zfe;
+}
+
+static PSI_ContextOps ops = {
+       init,
+       dtor,
+       compile,
+};
+
+PSI_ContextOps *PSI_Libjit(void)
+{
+       return &ops;
+}
diff --git a/src/libjit.h b/src/libjit.h
new file mode 100644 (file)
index 0000000..78012a6
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _PSI_LIBJIT_H
+#define _PSI_LIBJIT_H
+
+PSI_ContextOps *PSI_Libjit(void);
+
+#endif
index 69ec53d6b1d1d16bda64fd5fa23da779f62b231a..b8109b370e434bdba23ad0ac2c93c9eb924871fb 100644 (file)
@@ -4,13 +4,10 @@
 #endif
 
 #include <jit/jit.h>
 #endif
 
 #include <jit/jit.h>
-#include <dirent.h>
-#include <fnmatch.h>
 
 #include "php.h"
 #include "php_ini.h"
 #include "ext/standard/info.h"
 
 #include "php.h"
 #include "php_ini.h"
 #include "ext/standard/info.h"
-#include "php_scandir.h"
 
 #include "php_psi.h"
 
 
 #include "php_psi.h"
 
@@ -24,7 +21,7 @@ PHP_INI_BEGIN()
        STD_PHP_INI_ENTRY("psi.directory", "psis", PHP_INI_ALL, OnUpdateString, directory, zend_psi_globals, psi_globals)
 PHP_INI_END();
 
        STD_PHP_INI_ENTRY("psi.directory", "psis", PHP_INI_ALL, OnUpdateString, directory, zend_psi_globals, psi_globals)
 PHP_INI_END();
 
-static void psi_error(int type, const char *msg, ...)
+void psi_error(int type, const char *msg, ...)
 {
        char buf[0x1000];
        va_list argv;
 {
        char buf[0x1000];
        va_list argv;
@@ -36,82 +33,13 @@ static void psi_error(int type, const char *msg, ...)
        php_error(type, buf);
 }
 
        php_error(type, buf);
 }
 
-static int psi_select_dirent(const struct dirent *entry)
-{
-#ifndef FNM_CASEFOLD
-#define FNM_CASEFOLD 0
-#endif
-       return 0 == fnmatch("*.psi", entry->d_name, FNM_CASEFOLD);
-}
-
 PHP_MINIT_FUNCTION(psi)
 {
 PHP_MINIT_FUNCTION(psi)
 {
-       jit_context_t ctx;
-       int i, n;
-       struct dirent **entries = NULL;
-
        REGISTER_INI_ENTRIES();
 
        REGISTER_INI_ENTRIES();
 
-       jit_init();
-
-       if (!(ctx = jit_context_create())) {
-               zend_error(E_WARNING, "Could not initialize libjit!");
-               return FAILURE;
-       }
-
-       PSI_G(context) = ctx;
-
-       n = php_scandir(PSI_G(directory), &entries, psi_select_dirent, alphasort);
-       if (n < 0) {
-               php_error(E_WARNING, "Failed to scan PSI directory '%s'", PSI_G(directory));
-       } else for (i = 0; i < n; ++i) {
-               char psi[MAXPATHLEN];
-               PSI_Parser P;
-               PSI_Validator V;
-
-               if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", PSI_G(directory), entries[i]->d_name)) {
-                       php_error(E_WARNING, "Path to PSI file too long: %s/%s",
-                               PSI_G(directory), entries[i]->d_name);
-               }
-               if (!PSI_ParserInit(&P, psi, psi_error, 0)) {
-                       php_error(E_WARNING, "Failed to init PSI parser (%s): %s",
-                               psi, strerror(errno));
-                       continue;
-               }
-
-               while (-1 != PSI_ParserScan(&P)) {
-                       PSI_ParserParse(&P, PSI_TokenAlloc(&P));
-               };
-               PSI_ParserParse(&P, NULL);
-
-               if (!PSI_ValidatorInit(&V, &P)) {
-                       php_error(E_WARNING, "Failed to init PSI validator");
-                       break;
-               }
-               PSI_ParserDtor(&P);
-
-               if (PSI_ValidatorValidate(&V)) {
-                       PSI_Compiler C;
-
-                       jit_context_build_start(ctx);
-                       if (PSI_CompilerInit(&C, &V, ctx)) {
-                               zend_function_entry *closures = PSI_CompilerCompile(&C);
-
-                               if (closures && SUCCESS != zend_register_functions(NULL, closures, NULL, MODULE_PERSISTENT)) {
-                                       psi_error(E_WARNING, "Failed to register functions!");
-                               }
-                               //PSI_CompilerDtor(&C);
-                       }
-                       jit_context_build_end(ctx);
-               }
-               PSI_ValidatorDtor(&V);
-       }
-       if (entries) {
-               for (i = 0; i < n; ++i) {
-                       free(entries[i]);
-               }
-               free(entries);
-       }
+       PSI_ContextInit(&PSI_G(context), PSI_Libjit(), psi_error);
+       PSI_ContextBuild(&PSI_G(context), PSI_G(directory));
+
        return SUCCESS;
 }
 PHP_MSHUTDOWN_FUNCTION(psi)
        return SUCCESS;
 }
 PHP_MSHUTDOWN_FUNCTION(psi)