]> granicus.if.org Git - php/commitdiff
Move rare cases of DO_FCALL into separate helpers.
authorDmitry Stogov <dmitry@zend.com>
Wed, 13 Apr 2016 17:13:17 +0000 (20:13 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 13 Apr 2016 17:13:17 +0000 (20:13 +0300)
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 96c3bb1868124b2059dbcb90cabc1ce21d9e4f30..c276fb9f42ef582f66102cd21719d2b1b8f9b248 100644 (file)
@@ -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"
index 082fcddf6a0b62cdcaa928df2f009871c6bfda38..1382729278ae33f01a35d77f4e245f4136473c11 100644 (file)
@@ -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) {
index ea702fced027b9b79b141f15179ef4b28ce92180..5420d4f4cd741e69af49192523141cbdcafe41f4 100644 (file)
@@ -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) {