summaryrefslogtreecommitdiff
path: root/Zend/zend_closures.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_closures.c')
-rw-r--r--Zend/zend_closures.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index 637e2dd5fc..50aa7d4188 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -87,7 +87,7 @@ ZEND_METHOD(Closure, call)
}
zclosure = getThis();
- closure = (zend_closure *)Z_OBJ_P(zclosure);
+ closure = (zend_closure *) Z_OBJ_P(zclosure);
if (closure->func.common.fn_flags & ZEND_ACC_STATIC) {
zend_error(E_WARNING, "Cannot bind an instance to a static closure");
@@ -122,22 +122,32 @@ ZEND_METHOD(Closure, call)
fci.object = fci_cache.object = newobj;
fci_cache.initialized = 1;
- my_function = *fci_cache.function_handler;
- /* use scope of passed object */
- my_function.common.scope = Z_OBJCE_P(newthis);
- fci_cache.function_handler = &my_function;
-
- /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */
- if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
- my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size);
- memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size);
+ if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) {
+ zval new_closure;
+ zend_create_closure(&new_closure, fci_cache.function_handler, Z_OBJCE_P(newthis), closure->called_scope, newthis);
+ closure = (zend_closure *) Z_OBJ(new_closure);
+ fci_cache.function_handler = &closure->func;
+ } else {
+ memcpy(&my_function, fci_cache.function_handler, fci_cache.function_handler->type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function));
+ /* use scope of passed object */
+ my_function.common.scope = Z_OBJCE_P(newthis);
+ fci_cache.function_handler = &my_function;
+
+ /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */
+ if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
+ my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size);
+ memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size);
+ }
}
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) {
ZVAL_COPY_VALUE(return_value, &closure_result);
}
- if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
+ if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) {
+ /* copied upon generator creation */
+ --GC_REFCOUNT(&closure->std);
+ } else if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
efree(my_function.op_array.run_time_cache);
}
}