flush
[m6w6/ext-psi] / src / libjit.c
index b6022c5f92592cad376e14fd42e84deee6ef2e1d..23d53c16a4efe9ceb70702c1bf9634e4b36e5b1c 100644 (file)
@@ -1,5 +1,7 @@
 #ifdef HAVE_CONFIG_H
 # include "config.h"
+#else
+# include "php_config.h"
 #endif
 
 #include "php.h"
@@ -178,10 +180,6 @@ static inline jit_type_t psi_jit_decl_arg_type(decl_arg *darg) {
 struct psi_jit_context {
        jit_context_t jit;
        jit_type_t signature;
-       struct {
-               struct psi_jit_data **list;
-               size_t count;
-       } data;
 };
 
 struct psi_jit_call {
@@ -190,12 +188,6 @@ struct psi_jit_call {
        void *params[1]; /* [type1, type2, NULL, arg1, arg2] ... */
 };
 
-struct psi_jit_data {
-       struct psi_jit_context *context;
-       impl *impl;
-       zend_internal_arg_info *arginfo;
-};
-
 static inline struct psi_jit_call *psi_jit_call_alloc(struct psi_context *C, decl *decl) {
        size_t i, c = decl->args ? decl->args->count : 0;
        struct psi_jit_call *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *));
@@ -272,6 +264,37 @@ static void psi_jit_init(struct psi_context *C)
        C->context = psi_jit_context_init(NULL);
 }
 
+static inline void psi_jit_destroy_callbacks(struct psi_context *C, let_val *let_val) {
+       let_callback *cb;
+       let_func *fn = NULL;
+
+       switch (let_val->kind) {
+       case PSI_LET_CALLBACK:
+               cb = let_val->data.callback;
+
+               if (cb->decl && cb->decl->call.info) {
+                       psi_jit_call_free(cb->decl->call.info);
+               }
+               fn = cb->func;
+               /* no break */
+       case PSI_LET_FUNC:
+               if (!fn) {
+                       fn = let_val->data.func;
+               }
+
+               if (fn->inner) {
+                       size_t i;
+
+                       for (i = 0; i < fn->inner->count; ++i) {
+                               psi_jit_destroy_callbacks(C, fn->inner->vals[i]);
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+}
+
 static void psi_jit_dtor(struct psi_context *C)
 {
        if (C->decls) {
@@ -292,19 +315,46 @@ static void psi_jit_dtor(struct psi_context *C)
                        impl *impl = C->impls->list[i];
 
                        for (j = 0; j < impl->stmts->let.count; ++j) {
-                               let_stmt *let = impl->stmts->let.list[j];
+                               psi_jit_destroy_callbacks(C, impl->stmts->let.list[j]->val);
+                       }
+               }
+       }
+       psi_jit_context_free((void *) &C->context);
+}
 
-                               if (let->val && let->val->kind == PSI_LET_CALLBACK) {
-                                       let_callback *cb = let->val->data.callback;
+static inline void psi_jit_compile_callbacks(struct psi_context *C, let_val *let_val) {
+       struct psi_jit_call *call;
+       let_callback *cb;
+       let_func *fn = NULL;
 
-                                       if (cb->decl && cb->decl->call.info) {
-                                               psi_jit_call_free(cb->decl->call.info);
-                                       }
-                               }
+       switch (let_val->kind) {
+       case PSI_LET_CALLBACK:
+               cb = let_val->data.callback;
+               if ((call = psi_jit_call_alloc(C, cb->decl))) {
+                       if (!psi_jit_call_init_callback_closure(C, call, cb)) {
+                               psi_jit_call_free(call);
+                               break;
+                       }
+
+                       cb->decl->call.sym = call->closure;
+               }
+               fn = cb->func;
+               /* no break */
+       case PSI_LET_FUNC:
+               if (!fn) {
+                       fn = let_val->data.func;
+               }
+               if (fn->inner) {
+                       size_t i;
+
+                       for (i = 0; i < fn->inner->count; ++i) {
+                               psi_jit_compile_callbacks(C, fn->inner->vals[i]);
                        }
                }
+               break;
+       default:
+               break;
        }
-       psi_jit_context_free((void *) &C->context);
 }
 
 static zend_function_entry *psi_jit_compile(struct psi_context *C)
@@ -328,12 +378,12 @@ static zend_function_entry *psi_jit_compile(struct psi_context *C)
                if (!impl->decl) {
                        continue;
                }
-
-               if ((call = psi_jit_call_alloc(C, impl->decl))) {
-                       if (!psi_jit_call_init_closure(C, call, impl)) {
-                               psi_jit_call_free(call);
-                               continue;
-                       }
+               if (!(call = psi_jit_call_alloc(C, impl->decl))) {
+                       continue;
+               }
+               if (!psi_jit_call_init_closure(C, call, impl)) {
+                       psi_jit_call_free(call);
+                       continue;
                }
 
                zf->fname = impl->func->name + (impl->func->name[0] == '\\');
@@ -343,20 +393,7 @@ static zend_function_entry *psi_jit_compile(struct psi_context *C)
                ++j;
 
                for (c = 0; c < impl->stmts->let.count; ++c) {
-                       let_stmt *let = impl->stmts->let.list[c];
-
-                       if (let->val && let->val->kind == PSI_LET_CALLBACK) {
-                               let_callback *cb = let->val->data.callback;
-
-                               if ((call = psi_jit_call_alloc(C, cb->decl))) {
-                                       if (!psi_jit_call_init_callback_closure(C, call, cb)) {
-                                               psi_jit_call_free(call);
-                                               continue;
-                                       }
-
-                                       cb->decl->call.sym = call->closure;
-                               }
-                       }
+                       psi_jit_compile_callbacks(C, impl->stmts->let.list[c]->val);
                }
        }