FAQ
Commit: 86a1aeed227c1c73069cfae350197e992e3eb841
Author: Dmitry Stogov <dmitry@zend.com> Thu, 31 Mar 2016 18:58:13 +0300
Parents: fcbe1e8edf8614b098057d5c280f6bfbbe753faf
Branches: master

Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=86a1aeed227c1c73069cfae350197e992e3eb841

Log:
Flags ZEND_CALL_RELEASE_THIS and ZEND_CALL_CLOSURE should never be set together.
Closures keep responsibility for releasing $this theirselves.

Changed paths:
   M Zend/zend_execute.c
   M Zend/zend_generators.c
   M Zend/zend_vm_def.h
   M Zend/zend_vm_execute.h


Diff:
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 5abc2ad..9aa2d77 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -2311,9 +2311,6 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
   EG(vm_stack_end) = EG(vm_stack)->end;

   call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_ALLOCATED | (ZEND_CALL_INFO(call) & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS));
- if (Z_OBJ(call->This)) {
- call_info |= ZEND_CALL_RELEASE_THIS;
- }
   execute_data = zend_vm_stack_push_call_frame(
    call_info,
    (zend_function*)op_array,
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 5a3e84c..4e65c92 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -69,7 +69,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
    /* always free the CV's, in the symtable are only not-free'd IS_INDIRECT's */
    zend_free_compiled_variables(execute_data);

- if (Z_OBJ(execute_data->This)) {
+ if (EX_CALL_INFO() & ZEND_CALL_RELEASE_THIS) {
     OBJ_RELEASE(Z_OBJ(execute_data->This));
    }

@@ -334,7 +334,7 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array

   object_init_ex(return_value, zend_ce_generator);

- if (Z_OBJ(call->This)) {
+ if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
    Z_ADDREF(call->This);
   }

diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index b430395..ec147ec 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -2527,9 +2527,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
    zend_vm_stack_free_extra_args_ex(call_info, execute_data);
    old_execute_data = execute_data;
    execute_data = EG(current_execute_data) = EX(prev_execute_data);
- if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype);
- }
    if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
     object = Z_OBJ(old_execute_data->This);
  #if 0
@@ -2543,6 +2540,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
      }
     }
     OBJ_RELEASE(object);
+ } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
+ OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype);
    }
    EG(scope) = EX(func)->op_array.scope;

@@ -3583,6 +3582,8 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
   function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
   if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
    func = fcc.function_handler;
+ called_scope = fcc.called_scope;
+ object = fcc.object;
    if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
     /* Delay closure destruction until its invocation */
     if (OP2_TYPE & (IS_VAR|IS_CV)) {
@@ -3591,10 +3592,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
     ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
     GC_REFCOUNT((zend_object*)func->common.prototype)++;
     call_info |= ZEND_CALL_CLOSURE;
- }
- called_scope = fcc.called_scope;
- object = fcc.object;
- if (object) {
+ } else if (object) {
     call_info |= ZEND_CALL_RELEASE_THIS;
     GC_REFCOUNT(object)++; /* For $this pointer */
    }
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 69df98c..7c3efd4 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -484,9 +484,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
    zend_vm_stack_free_extra_args_ex(call_info, execute_data);
    old_execute_data = execute_data;
    execute_data = EG(current_execute_data) = EX(prev_execute_data);
- if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype);
- }
    if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
     object = Z_OBJ(old_execute_data->This);
  #if 0
@@ -500,6 +497,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
      }
     }
     OBJ_RELEASE(object);
+ } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
+ OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype);
    }
    EG(scope) = EX(func)->op_array.scope;

@@ -6198,6 +6197,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
   function_name = EX_CONSTANT(opline->op2);
   if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
    func = fcc.function_handler;
+ called_scope = fcc.called_scope;
+ object = fcc.object;
    if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
     /* Delay closure destruction until its invocation */
     if (IS_CONST & (IS_VAR|IS_CV)) {
@@ -6206,10 +6207,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
     ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
     GC_REFCOUNT((zend_object*)func->common.prototype)++;
     call_info |= ZEND_CALL_CLOSURE;
- }
- called_scope = fcc.called_scope;
- object = fcc.object;
- if (object) {
+ } else if (object) {
     call_info |= ZEND_CALL_RELEASE_THIS;
     GC_REFCOUNT(object)++; /* For $this pointer */
    }
@@ -10006,6 +10004,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
   function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
   if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
    func = fcc.function_handler;
+ called_scope = fcc.called_scope;
+ object = fcc.object;
    if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
     /* Delay closure destruction until its invocation */
     if (IS_CV & (IS_VAR|IS_CV)) {
@@ -10014,10 +10014,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
     ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
     GC_REFCOUNT((zend_object*)func->common.prototype)++;
     call_info |= ZEND_CALL_CLOSURE;
- }
- called_scope = fcc.called_scope;
- object = fcc.object;
- if (object) {
+ } else if (object) {
     call_info |= ZEND_CALL_RELEASE_THIS;
     GC_REFCOUNT(object)++; /* For $this pointer */
    }
@@ -11913,6 +11910,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
   function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
   if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
    func = fcc.function_handler;
+ called_scope = fcc.called_scope;
+ object = fcc.object;
    if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
     /* Delay closure destruction until its invocation */
     if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) {
@@ -11921,10 +11920,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
     ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
     GC_REFCOUNT((zend_object*)func->common.prototype)++;
     call_info |= ZEND_CALL_CLOSURE;
- }
- called_scope = fcc.called_scope;
- object = fcc.object;
- if (object) {
+ } else if (object) {
     call_info |= ZEND_CALL_RELEASE_THIS;
     GC_REFCOUNT(object)++; /* For $this pointer */
    }

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupphp-cvs @
categoriesphp
postedMar 31, '16 at 4:00p
activeMar 31, '16 at 4:00p
posts1
users1
websitephp.net

1 user in discussion

Dmitry Stogov: 1 post

People

Translate

site design / logo © 2019 Grokbase