From: Dmitry Stogov Date: Wed, 13 Apr 2016 17:13:17 +0000 (+0300) Subject: Move rare cases of DO_FCALL into separate helpers. X-Git-Tag: php-7.1.0alpha1~329^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e95efb6312e96e2f4d6431e30266c9e339dc9a4c;p=php Move rare cases of DO_FCALL into separate helpers. --- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 96c3bb1868..c276fb9f42 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -769,6 +769,23 @@ static int zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zv return 1; } +static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call) +{ + uint32_t i; + uint32_t num_args = ZEND_CALL_NUM_ARGS(call); + zval *p = ZEND_CALL_ARG(call, 1); + + for (i = 0; i < num_args; ++i) { + if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call); + return 0; + } + p++; + } + return 1; +} + static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot) { zend_arg_info *cur_arg_info; @@ -2930,6 +2947,44 @@ already_compiled: } /* }}} */ +static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_execute_data *call, zval *ret) /* {{{ */ +{ + zend_object *object; + + /* Not sure what should be done here if it's a static method */ + if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) { + zend_vm_stack_free_args(call); + if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { + zend_string_release(fbc->common.function_name); + } + efree(fbc); + zend_vm_stack_free_call_frame(call); + + zend_throw_error(NULL, "Cannot call overloaded function for non-object"); + return 0; + } + + object = Z_OBJ(call->This); + EG(scope) = fbc->common.scope; + + ZVAL_NULL(ret); + Z_VAR_FLAGS_P(ret) = 0; + + EG(current_execute_data) = call; + object->handlers->call_method(fbc->common.function_name, object, call, ret); + EG(current_execute_data) = call->prev_execute_data; + + zend_vm_stack_free_args(call); + + if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { + zend_string_release(fbc->common.function_name); + } + efree(fbc); + + return 1; +} +/* }}} */ + #ifdef HAVE_GCC_GLOBAL_REGS # if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386) # define ZEND_VM_FP_GLOBAL_REG "%esi" diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 082fcddf6a..1382729278 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3617,21 +3617,11 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - uint32_t i; - uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - - for (i = 0; i < num_args; ++i) { - if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } - p++; - } + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) + && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { + zend_vm_stack_free_call_frame(call); + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; @@ -3739,25 +3729,15 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - uint32_t i; - uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - - for (i = 0; i < num_args; ++i) { - if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - if (RETURN_VALUE_USED(opline)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } - if (UNEXPECTED(should_change_scope)) { - ZEND_VM_C_GOTO(fcall_end_change_scope); - } else { - ZEND_VM_C_GOTO(fcall_end); - } - } - p++; + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) + && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + if (UNEXPECTED(should_change_scope)) { + ZEND_VM_C_GOTO(fcall_end_change_scope); + } else { + ZEND_VM_C_GOTO(fcall_end); } } @@ -3793,41 +3773,17 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) } } else { /* ZEND_OVERLOADED_FUNCTION */ zval retval; - /* Not sure what should be done here if it's a static method */ - if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) { - zend_vm_stack_free_args(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release(fbc->common.function_name); - } - efree(fbc); - zend_vm_stack_free_call_frame(call); - - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - HANDLE_EXCEPTION(); - } - - object = Z_OBJ(call->This); - EG(scope) = fbc->common.scope; ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; - ZVAL_NULL(ret); call->prev_execute_data = execute_data; - EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, ret); - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release(fbc->common.function_name); + if (UNEXPECTED(!zend_do_fcall_overloaded(fbc, call, ret))) { + HANDLE_EXCEPTION(); } - efree(fbc); if (!RETURN_VALUE_USED(opline)) { zval_ptr_dtor(ret); - } else { - Z_VAR_FLAGS_P(ret) = 0; } } @@ -7922,25 +7878,13 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) EG(current_execute_data) = call; - if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - uint32_t i; - uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - - EG(current_execute_data) = call; - - for (i = 0; i < num_args; ++i) { - if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - if (ret) { - ZVAL_UNDEF(ret); - } - ZEND_VM_C_GOTO(call_trampoline_end); - } - p++; + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) + && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { + zend_vm_stack_free_call_frame(call); + if (ret) { + ZVAL_UNDEF(ret); } + ZEND_VM_C_GOTO(call_trampoline_end); } if (ret == NULL) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ea702fced0..5420d4f4cd 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -793,21 +793,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - uint32_t i; - uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - - for (i = 0; i < num_args; ++i) { - if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } - p++; - } + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) + && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { + zend_vm_stack_free_call_frame(call); + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } ret = 0 ? EX_VAR(opline->result.var) : &retval; @@ -897,21 +887,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - uint32_t i; - uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - - for (i = 0; i < num_args; ++i) { - if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } - p++; - } + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) + && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { + zend_vm_stack_free_call_frame(call); + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } ret = 1 ? EX_VAR(opline->result.var) : &retval; @@ -1019,25 +999,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - uint32_t i; - uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - - for (i = 0; i < num_args; ++i) { - if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - if (0) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } - if (UNEXPECTED(should_change_scope)) { - goto fcall_end_change_scope; - } else { - goto fcall_end; - } - } - p++; + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) + && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { + if (0) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + if (UNEXPECTED(should_change_scope)) { + goto fcall_end_change_scope; + } else { + goto fcall_end; } } @@ -1073,41 +1043,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA } } else { /* ZEND_OVERLOADED_FUNCTION */ zval retval; - /* Not sure what should be done here if it's a static method */ - if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) { - zend_vm_stack_free_args(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release(fbc->common.function_name); - } - efree(fbc); - zend_vm_stack_free_call_frame(call); - - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - HANDLE_EXCEPTION(); - } - - object = Z_OBJ(call->This); - EG(scope) = fbc->common.scope; ret = 0 ? EX_VAR(opline->result.var) : &retval; - ZVAL_NULL(ret); call->prev_execute_data = execute_data; - EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, ret); - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release(fbc->common.function_name); + if (UNEXPECTED(!zend_do_fcall_overloaded(fbc, call, ret))) { + HANDLE_EXCEPTION(); } - efree(fbc); if (!0) { zval_ptr_dtor(ret); - } else { - Z_VAR_FLAGS_P(ret) = 0; } } @@ -1214,25 +1160,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - uint32_t i; - uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - - for (i = 0; i < num_args; ++i) { - if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - if (1) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } - if (UNEXPECTED(should_change_scope)) { - goto fcall_end_change_scope; - } else { - goto fcall_end; - } - } - p++; + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) + && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { + if (1) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + if (UNEXPECTED(should_change_scope)) { + goto fcall_end_change_scope; + } else { + goto fcall_end; } } @@ -1268,41 +1204,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND } } else { /* ZEND_OVERLOADED_FUNCTION */ zval retval; - /* Not sure what should be done here if it's a static method */ - if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) { - zend_vm_stack_free_args(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release(fbc->common.function_name); - } - efree(fbc); - zend_vm_stack_free_call_frame(call); - - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - HANDLE_EXCEPTION(); - } - - object = Z_OBJ(call->This); - EG(scope) = fbc->common.scope; ret = 1 ? EX_VAR(opline->result.var) : &retval; - ZVAL_NULL(ret); call->prev_execute_data = execute_data; - EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, ret); - EG(current_execute_data) = call->prev_execute_data; - - zend_vm_stack_free_args(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release(fbc->common.function_name); + if (UNEXPECTED(!zend_do_fcall_overloaded(fbc, call, ret))) { + HANDLE_EXCEPTION(); } - efree(fbc); if (!1) { zval_ptr_dtor(ret); - } else { - Z_VAR_FLAGS_P(ret) = 0; } } @@ -2148,25 +2060,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z EG(current_execute_data) = call; - if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - uint32_t i; - uint32_t num_args = ZEND_CALL_NUM_ARGS(call); - zval *p = ZEND_CALL_ARG(call, 1); - - EG(current_execute_data) = call; - - for (i = 0; i < num_args; ++i) { - if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - if (ret) { - ZVAL_UNDEF(ret); - } - goto call_trampoline_end; - } - p++; + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) + && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { + zend_vm_stack_free_call_frame(call); + if (ret) { + ZVAL_UNDEF(ret); } + goto call_trampoline_end; } if (ret == NULL) {