From: Dmitry Stogov Date: Thu, 7 May 2015 13:28:23 +0000 (+0300) Subject: Avoid unnecessary reference counter incrementation on $this when call methods X-Git-Tag: PRE_PHP7_NSAPI_REMOVAL~68 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ab4ccffc4cceb877d2ce3144e5c499bd651886bf;p=php Avoid unnecessary reference counter incrementation on $this when call methods --- diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 575dbe0803..8c1e49df3d 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -454,6 +454,7 @@ struct _zend_execute_data { #define ZEND_CALL_CTOR (1 << 3) #define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 4) #define ZEND_CALL_CLOSURE (1 << 5) +#define ZEND_CALL_RELEASE_THIS (1 << 6) #define ZEND_CALL_INFO(call) \ (Z_TYPE_INFO((call)->This) >> 24) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 648b80c069..26415b0d7c 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2067,6 +2067,7 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data zend_execute_data *execute_data; uint32_t num_args = ZEND_CALL_NUM_ARGS(call); size_t stack_size = (ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)) * sizeof(zval); + uint32_t call_info; EG(vm_stack) = zend_vm_stack_new_page( EXPECTED(stack_size < ZEND_VM_STACK_FREE_PAGE_SIZE(1)) ? @@ -2076,8 +2077,12 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data EG(vm_stack_top) = EG(vm_stack)->top; EG(vm_stack_end) = EG(vm_stack)->end; + call_info = ZEND_CALL_TOP_FUNCTION | (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( - ZEND_CALL_TOP_FUNCTION | (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE), + call_info, (zend_function*)op_array, num_args, call->called_scope, diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index ab32d9ad12..a7ab662c99 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -825,12 +825,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / if (func->common.fn_flags & ZEND_ACC_STATIC) { fci->object = NULL; } - if (!fci->object) { - Z_OBJ(call->This) = NULL; - } else { - Z_OBJ(call->This) = fci->object; - GC_REFCOUNT(fci->object)++; - } + Z_OBJ(call->This) = fci->object; if (func->type == ZEND_USER_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; @@ -868,7 +863,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); /* We shouldn't fix bad extensions here, because it can break proper ones (Bug #34045) @@ -899,7 +893,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { zend_string_release(func->common.function_name); @@ -912,11 +905,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } } - if (fci->object) { - OBJ_RELEASE(fci->object); - } - EG(scope) = orig_scope; + zend_vm_stack_free_call_frame(call); + if (EG(current_execute_data) == &dummy_execute_data) { EG(current_execute_data) = dummy_execute_data.prev_execute_data; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e00ee07d84..3cbd5143a5 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2401,12 +2401,15 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype); } - object = Z_OBJ(old_execute_data->This); - zend_vm_stack_free_call_frame(old_execute_data); - - if (object) { + if (call_info & ZEND_CALL_RELEASE_THIS) { + object = Z_OBJ(old_execute_data->This); +#if 0 if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { +#else + if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { + if (!(call_info & ZEND_CALL_CTOR_RESULT_UNUSED)) { +#endif GC_REFCOUNT(object)--; } if (GC_REFCOUNT(object) == 1) { @@ -2417,6 +2420,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) } EG(scope) = EX(func)->op_array.scope; + zend_vm_stack_free_call_frame(old_execute_data); + if (UNEXPECTED(EG(exception) != NULL)) { const zend_op *old_opline = EX(opline); zend_throw_exception_internal(NULL); @@ -2882,6 +2887,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -2959,13 +2965,15 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -3070,7 +3078,6 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -3175,9 +3182,6 @@ ZEND_VM_C_LABEL(try_function_name): EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) { - if (object) { - GC_REFCOUNT(object)++; - } if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ ZEND_ASSERT(GC_TYPE(fbc->common.prototype) == IS_OBJECT); @@ -3262,6 +3266,7 @@ ZEND_VM_C_LABEL(try_function_name): if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { object = NULL; } else { + call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ } } @@ -3318,6 +3323,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV) called_scope = fcc.called_scope; object = fcc.object; if (object) { + call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ } else if (func->common.scope && !(func->common.fn_flags & ZEND_ACC_STATIC)) { @@ -3595,7 +3601,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) USE_OPLINE zend_execute_data *call = EX(call); zend_function *fbc = call->func; - zend_object *object = Z_OBJ(call->This); + zend_object *object; zval *ret; SAVE_OPLINE(); @@ -3628,8 +3634,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) } else { zend_vm_stack_free_args(call); } - - zend_vm_stack_free_call_frame(call); } else { ret = NULL; call->symbol_table = NULL; @@ -3670,7 +3674,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) if (UNEXPECTED(EG(exception) != NULL)) { EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); if (RETURN_VALUE_USED(opline)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } @@ -3704,7 +3707,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); if (!RETURN_VALUE_USED(opline)) { zval_ptr_dtor(EX_VAR(opline->result.var)); @@ -3721,6 +3723,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) ZVAL_NULL(EX_VAR(opline->result.var)); /* Not sure what should be done here if it's a static method */ + object = Z_OBJ(call->This); if (EXPECTED(object != NULL)) { call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -3744,8 +3747,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { zend_string_release(fbc->common.function_name); } @@ -3759,9 +3760,15 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) } ZEND_VM_C_LABEL(fcall_end_change_scope): - if (object) { + if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { + object = Z_OBJ(call->This); +#if 0 if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) { if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { +#else + if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) { + if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) { +#endif GC_REFCOUNT(object)--; } if (GC_REFCOUNT(object) == 1) { @@ -3773,6 +3780,7 @@ ZEND_VM_C_LABEL(fcall_end_change_scope): EG(scope) = EX(func)->op_array.scope; ZEND_VM_C_LABEL(fcall_end): + zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); if (RETURN_VALUE_USED(opline)) { @@ -4891,7 +4899,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY) } else { /* We are not handling overloaded classes right now */ zend_execute_data *call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_CTOR | + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | (EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), constructor, opline->extended_value, @@ -7121,7 +7129,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) zend_vm_stack_free_args(EX(call)); - if (Z_OBJ(call->This)) { + if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) { if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) { GC_REFCOUNT(Z_OBJ(call->This))--; @@ -7882,7 +7890,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) zend_function *fbc = EX(func); zend_object *object = Z_OBJ(EX(This)); zval *ret = EX(return_value); - zend_call_kind call_kind = EX_CALL_KIND(); + uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS); zend_class_entry *scope = EX(called_scope); uint32_t num_args = EX_NUM_ARGS(); zend_execute_data *call; @@ -7907,7 +7915,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) call = execute_data; execute_data = EG(current_execute_data) = EX(prev_execute_data); zend_vm_stack_free_call_frame(call); - call = zend_vm_stack_push_call_frame(call_kind, fbc->common.prototype, 2, scope, object); + call = zend_vm_stack_push_call_frame(call_info, fbc->common.prototype, 2, scope, object); call->prev_execute_data = execute_data; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); @@ -7981,7 +7989,6 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); if (ret == &retval) { zval_ptr_dtor(ret); @@ -7991,16 +7998,18 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) ZEND_VM_C_LABEL(call_trampoline_end): execute_data = EG(current_execute_data); - if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_kind & ZEND_CALL_TOP)) { + if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { ZEND_VM_RETURN(); } opline = EX(opline); - if (object) { + if (call_info & ZEND_CALL_RELEASE_THIS) { + object = Z_OBJ(call->This); OBJ_RELEASE(object); } EG(scope) = EX(func)->op_array.scope; + zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 85075af2a6..73e2a4a6ca 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -452,12 +452,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype); } - object = Z_OBJ(old_execute_data->This); - zend_vm_stack_free_call_frame(old_execute_data); - - if (object) { + if (call_info & ZEND_CALL_RELEASE_THIS) { + object = Z_OBJ(old_execute_data->This); +#if 0 if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { +#else + if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { + if (!(call_info & ZEND_CALL_CTOR_RESULT_UNUSED)) { +#endif GC_REFCOUNT(object)--; } if (GC_REFCOUNT(object) == 1) { @@ -468,6 +471,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ } EG(scope) = EX(func)->op_array.scope; + zend_vm_stack_free_call_frame(old_execute_data); + if (UNEXPECTED(EG(exception) != NULL)) { const zend_op *old_opline = EX(opline); zend_throw_exception_internal(NULL); @@ -718,7 +723,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC USE_OPLINE zend_execute_data *call = EX(call); zend_function *fbc = call->func; - zend_object *object = Z_OBJ(call->This); + zend_object *object; zval *ret; SAVE_OPLINE(); @@ -751,8 +756,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC } else { zend_vm_stack_free_args(call); } - - zend_vm_stack_free_call_frame(call); } else { ret = NULL; call->symbol_table = NULL; @@ -793,7 +796,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC if (UNEXPECTED(EG(exception) != NULL)) { EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); if (RETURN_VALUE_USED(opline)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } @@ -827,7 +829,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); if (!RETURN_VALUE_USED(opline)) { zval_ptr_dtor(EX_VAR(opline->result.var)); @@ -844,6 +845,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC ZVAL_NULL(EX_VAR(opline->result.var)); /* Not sure what should be done here if it's a static method */ + object = Z_OBJ(call->This); if (EXPECTED(object != NULL)) { call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -867,8 +869,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { zend_string_release(fbc->common.function_name); } @@ -882,9 +882,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC } fcall_end_change_scope: - if (object) { + if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { + object = Z_OBJ(call->This); +#if 0 if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) { if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { +#else + if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) { + if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) { +#endif GC_REFCOUNT(object)--; } if (GC_REFCOUNT(object) == 1) { @@ -896,6 +902,7 @@ fcall_end_change_scope: EG(scope) = EX(func)->op_array.scope; fcall_end: + zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); if (RETURN_VALUE_USED(opline)) { @@ -1571,7 +1578,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( zend_vm_stack_free_args(EX(call)); - if (Z_OBJ(call->This)) { + if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) { if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) { GC_REFCOUNT(Z_OBJ(call->This))--; @@ -1829,7 +1836,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z zend_function *fbc = EX(func); zend_object *object = Z_OBJ(EX(This)); zval *ret = EX(return_value); - zend_call_kind call_kind = EX_CALL_KIND(); + uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS); zend_class_entry *scope = EX(called_scope); uint32_t num_args = EX_NUM_ARGS(); zend_execute_data *call; @@ -1854,7 +1861,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z call = execute_data; execute_data = EG(current_execute_data) = EX(prev_execute_data); zend_vm_stack_free_call_frame(call); - call = zend_vm_stack_push_call_frame(call_kind, fbc->common.prototype, 2, scope, object); + call = zend_vm_stack_push_call_frame(call_info, fbc->common.prototype, 2, scope, object); call->prev_execute_data = execute_data; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); @@ -1928,7 +1935,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); if (ret == &retval) { zval_ptr_dtor(ret); @@ -1938,16 +1944,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z call_trampoline_end: execute_data = EG(current_execute_data); - if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_kind & ZEND_CALL_TOP)) { + if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { ZEND_VM_RETURN(); } opline = EX(opline); - if (object) { + if (call_info & ZEND_CALL_RELEASE_THIS) { + object = Z_OBJ(call->This); OBJ_RELEASE(object); } EG(scope) = EX(func)->op_array.scope; + zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); @@ -2070,9 +2078,6 @@ try_function_name: EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) { - if (object) { - GC_REFCOUNT(object)++; - } if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ ZEND_ASSERT(GC_TYPE(fbc->common.prototype) == IS_OBJECT); @@ -2157,6 +2162,7 @@ try_function_name: if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { object = NULL; } else { + call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ } } @@ -2482,9 +2488,6 @@ try_function_name: EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) { - if (object) { - GC_REFCOUNT(object)++; - } if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ ZEND_ASSERT(GC_TYPE(fbc->common.prototype) == IS_OBJECT); @@ -2569,6 +2572,7 @@ try_function_name: if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { object = NULL; } else { + call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ } } @@ -2676,9 +2680,6 @@ try_function_name: EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) { - if (object) { - GC_REFCOUNT(object)++; - } if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ ZEND_ASSERT(GC_TYPE(fbc->common.prototype) == IS_OBJECT); @@ -2763,6 +2764,7 @@ try_function_name: if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { object = NULL; } else { + call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ } } @@ -3356,7 +3358,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP } else { /* We are not handling overloaded classes right now */ zend_execute_data *call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_CTOR | + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | (EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), constructor, opline->extended_value, @@ -5398,6 +5400,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -5475,13 +5478,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -5584,7 +5589,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -5654,6 +5658,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS called_scope = fcc.called_scope; object = fcc.object; if (object) { + call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ } else if (func->common.scope && !(func->common.fn_flags & ZEND_ACC_STATIC)) { @@ -7573,7 +7578,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -9036,6 +9040,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -9113,13 +9118,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -9222,7 +9229,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -9292,6 +9298,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H called_scope = fcc.called_scope; object = fcc.object; if (object) { + call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ } else if (func->common.scope && !(func->common.fn_flags & ZEND_ACC_STATIC)) { @@ -10761,6 +10768,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -10838,13 +10846,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -10948,7 +10958,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -11018,6 +11027,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV called_scope = fcc.called_scope; object = fcc.object; if (object) { + call_info |= ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(object)++; /* For $this pointer */ } else if (func->common.scope && !(func->common.fn_flags & ZEND_ACC_STATIC)) { @@ -15064,7 +15074,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCO } else { /* We are not handling overloaded classes right now */ zend_execute_data *call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_CTOR | + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | (EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), constructor, opline->extended_value, @@ -17304,7 +17314,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -18914,7 +18923,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -20611,7 +20619,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -22255,7 +22262,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) { object = Z_OBJ(EX(This)); - GC_REFCOUNT(object)++; } if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -23618,6 +23624,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -23695,13 +23702,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -26009,6 +26018,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -26086,13 +26096,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -27522,6 +27534,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -27599,13 +27612,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -31799,6 +31814,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -31876,13 +31892,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -36856,6 +36874,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -36933,13 +36952,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -39414,6 +39435,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -39491,13 +39513,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -41555,6 +41579,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -41632,13 +41657,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -43614,6 +43641,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -43691,13 +43719,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -44661,6 +44691,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T zend_class_entry *called_scope; zend_object *obj; zend_execute_data *call; + uint32_t call_info; SAVE_OPLINE(); @@ -44738,13 +44769,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } } + call_info = ZEND_CALL_NESTED_FUNCTION; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; - } else { + } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; GC_REFCOUNT(obj)++; /* For $this pointer */ } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = zend_vm_stack_push_call_frame(call_info, fbc, opline->extended_value, called_scope, obj); call->prev_execute_data = EX(call); EX(call) = call;