diff options
author | Dmitry Stogov <dmitry@zend.com> | 2019-04-12 02:35:42 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2019-04-12 02:35:42 +0300 |
commit | 55cc280429c453a89e33de7357fa80589470dfc3 (patch) | |
tree | 4185afc2c6405d42751fc354a20676be9408d904 /Zend/zend_vm_execute.h | |
parent | 88a2268d6b9ff152399a8761dc826ce414c0b985 (diff) | |
download | php-git-55cc280429c453a89e33de7357fa80589470dfc3.tar.gz |
Backported call frame initialization improvement
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r-- | Zend/zend_vm_execute.h | 560 |
1 files changed, 302 insertions, 258 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ad4f978ad1..a84ae4ec75 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1451,7 +1451,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_CREATE_SPEC_HANDLER( gen_execute_data->return_value = (zval*)generator; call_info = Z_TYPE_INFO(EX(This)); if ((call_info & Z_TYPE_MASK) == IS_OBJECT - && (!(call_info & ((ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS) << ZEND_CALL_INFO_SHIFT)) + && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS)) /* Bug #72523 */ || UNEXPECTED(zend_execute_ex != execute_ex))) { ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS); @@ -1668,13 +1668,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func)); - } - if (Z_TYPE(EX(call)->This) == IS_OBJECT) { + } else if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_RELEASE_THIS) { OBJ_RELEASE(Z_OBJ(EX(call)->This)); } EX(call)->func = (zend_function*)&zend_pass_function; Z_OBJ(EX(call)->This) = NULL; - ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); + ZEND_CALL_INFO(EX(call)) &= ~(ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS); FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); } else { uint32_t arg_num; @@ -2299,7 +2298,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME CACHE_PTR(opline->result.num, fbc); } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -2388,7 +2387,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -2419,7 +2418,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CO call = zend_vm_stack_push_call_frame_ex( opline->op1.num, ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3460,10 +3459,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -5412,26 +5411,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -5443,7 +5444,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -5544,33 +5545,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_CONST == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -5585,8 +5587,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; @@ -5594,8 +5595,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS function_name = RT_CONSTANT(opline, 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 (error) { efree(error); /* This is the only soft error is_callable() can generate */ @@ -5605,6 +5604,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS HANDLE_EXCEPTION(); } } + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -5612,17 +5612,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } - } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; - GC_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } if ((IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { if (call_info & ZEND_CALL_CLOSURE) { zend_object_release(ZEND_CLOSURE_OBJECT(func)); - } - if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + } else if (call_info & ZEND_CALL_RELEASE_THIS) { + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -5638,12 +5642,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS HANDLE_EXCEPTION(); } func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; + object_or_called_scope = NULL; } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -7659,26 +7662,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -7690,7 +7695,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -7791,33 +7796,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_CONST == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -7832,8 +7838,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; @@ -7841,8 +7846,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); 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 (error) { efree(error); /* This is the only soft error is_callable() can generate */ @@ -7852,6 +7855,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV HANDLE_EXCEPTION(); } } + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -7859,18 +7863,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } - } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; - GC_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } zval_ptr_dtor_nogc(free_op2); if (((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { if (call_info & ZEND_CALL_CLOSURE) { zend_object_release(ZEND_CLOSURE_OBJECT(func)); - } - if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + } else if (call_info & ZEND_CALL_RELEASE_THIS) { + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -7886,12 +7894,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV HANDLE_EXCEPTION(); } func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; + object_or_called_scope = NULL; } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -8841,7 +8848,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -8942,33 +8949,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_CONST == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -9077,17 +9085,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -10602,26 +10609,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -10633,7 +10642,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -10734,33 +10743,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_CONST == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -10775,8 +10785,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; @@ -10784,8 +10793,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H function_name = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); 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 (error) { efree(error); /* This is the only soft error is_callable() can generate */ @@ -10795,6 +10802,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H HANDLE_EXCEPTION(); } } + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -10802,17 +10810,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } - } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; - GC_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } if ((IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { if (call_info & ZEND_CALL_CLOSURE) { zend_object_release(ZEND_CLOSURE_OBJECT(func)); - } - if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + } else if (call_info & ZEND_CALL_RELEASE_THIS) { + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -10828,12 +10840,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H HANDLE_EXCEPTION(); } func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; + object_or_called_scope = NULL; } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -12919,10 +12930,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -14337,27 +14348,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -15972,27 +15985,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -17635,27 +17650,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -24510,7 +24527,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -24611,33 +24628,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_VAR == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -27209,7 +27227,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -27310,33 +27328,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_VAR == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -28889,7 +28908,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -28990,33 +29009,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_VAR == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -29125,17 +29145,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -31617,7 +31636,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -31718,33 +31737,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_VAR == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -33889,26 +33909,28 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -33920,7 +33942,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -34021,33 +34043,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -35837,26 +35860,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -35868,7 +35893,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -35969,33 +35994,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -36400,7 +36426,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -36501,33 +36527,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -36636,17 +36663,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -38430,26 +38456,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -38461,7 +38489,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -38562,33 +38590,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } + goto check_parent_and_self; } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { +check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -39936,10 +39965,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -43870,26 +43899,28 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -47977,26 +48008,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -54050,26 +54083,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -65456,13 +65491,22 @@ zend_leave_helper_SPEC_LABEL: ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value) { zend_execute_data *execute_data; + void *object_or_called_scope; + uint32_t call_info; if (EG(exception) != NULL) { return; } - execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, - (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data))); + object_or_called_scope = zend_get_this_object(EG(current_execute_data)); + if (EXPECTED(!object_or_called_scope)) { + object_or_called_scope = zend_get_called_scope(EG(current_execute_data)); + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE; + } else { + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE | ZEND_CALL_HAS_THIS; + } + execute_data = zend_vm_stack_push_call_frame(call_info, + (zend_function*)op_array, 0, object_or_called_scope); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(); } else { |