]> granicus.if.org Git - php/commitdiff
Avoid repeatable ARG_SHOULD_BE_SENT_BY_REF() checks in FETCH_*FUNC_ARG and following...
authorDmitry Stogov <dmitry@zend.com>
Mon, 5 Feb 2018 16:40:06 +0000 (19:40 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 5 Feb 2018 16:40:06 +0000 (19:40 +0300)
16 files changed:
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_gen.php
Zend/zend_vm_opcodes.c
Zend/zend_vm_opcodes.h
ext/opcache/Optimizer/optimize_func_calls.c
ext/opcache/Optimizer/sccp.c
ext/opcache/Optimizer/zend_call_graph.c
ext/opcache/Optimizer/zend_dfg.c
ext/opcache/Optimizer/zend_dump.c
ext/opcache/Optimizer/zend_inference.c
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/Optimizer/zend_ssa.c

index 0b4941e1f463f7a8d9acdba1c17240e818cdd150..3d9b2e77c6938cae48f2c9caf3914a8f5f273a0c 100644 (file)
@@ -1957,7 +1957,7 @@ static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
 {
        zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
 
-       switch (type & BP_VAR_MASK) {
+       switch (type) {
                case BP_VAR_R:
                        return;
                case BP_VAR_W:
@@ -1971,7 +1971,6 @@ static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
                        return;
                case BP_VAR_FUNC_ARG:
                        opline->opcode += 4 * factor;
-                       opline->extended_value |= type >> BP_VAR_SHIFT;
                        return;
                case BP_VAR_UNSET:
                        opline->opcode += 5 * factor;
@@ -3249,9 +3248,23 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
                                        opcode = ZEND_SEND_VAR;
                                }
                        } else {
-                               zend_compile_var(&arg_node, arg,
-                                       BP_VAR_FUNC_ARG | (arg_num << BP_VAR_SHIFT));
-                               opcode = ZEND_SEND_VAR_EX;
+                               do {
+                                       if (arg->kind == ZEND_AST_VAR) {
+                                               CG(zend_lineno) = zend_ast_get_lineno(ast);
+                                               if (is_this_fetch(arg)) {
+                                                       zend_emit_op(&arg_node, ZEND_FETCH_THIS, NULL, NULL);
+                                                       opcode = ZEND_SEND_VAR_EX;
+                                                       break;
+                                               } else if (zend_try_compile_cv(&arg_node, arg) == SUCCESS) {
+                                                       opcode = ZEND_SEND_VAR_EX;
+                                                       break;
+                                               }
+                                       }
+                                       opline = zend_emit_op(NULL, ZEND_CHECK_FUNC_ARG, NULL, NULL);
+                                       opline->op2.num = arg_num;
+                                       zend_compile_var(&arg_node, arg, BP_VAR_FUNC_ARG);
+                                       opcode = ZEND_SEND_FUNC_ARG;
+                               } while (0);
                        }
                } else {
                        zend_compile_expr(&arg_node, arg);
index e26d6c7cc4d2e6c919ab980f008d5d47a18f1b57..65a03e6b0e7ff44e04f80d2e1b988751fca18e3f 100644 (file)
@@ -481,6 +481,7 @@ struct _zend_execute_data {
 #define ZEND_CALL_GENERATOR          (1 << 8)
 #define ZEND_CALL_DYNAMIC            (1 << 9)
 #define ZEND_CALL_FAKE_CLOSURE       (1 << 10)
+#define ZEND_CALL_SEND_ARG_BY_REF    (1 << 11)
 
 #define ZEND_CALL_INFO_SHIFT         16
 
@@ -501,10 +502,18 @@ struct _zend_execute_data {
                call_info |= ((flag) << ZEND_CALL_INFO_SHIFT); \
        } while (0)
 
+#define ZEND_DEL_CALL_FLAG_EX(call_info, flag) do { \
+               call_info &= ~((flag) << ZEND_CALL_INFO_SHIFT); \
+       } while (0)
+
 #define ZEND_ADD_CALL_FLAG(call, flag) do { \
                ZEND_ADD_CALL_FLAG_EX(Z_TYPE_INFO((call)->This), flag); \
        } while (0)
 
+#define ZEND_DEL_CALL_FLAG(call, flag) do { \
+               ZEND_DEL_CALL_FLAG_EX(Z_TYPE_INFO((call)->This), flag); \
+       } while (0)
+
 #define ZEND_CALL_NUM_ARGS(call) \
        (call)->This.u2.num_args
 
@@ -840,11 +849,6 @@ void zend_assert_valid_class_name(const zend_string *const_name);
 #define BP_VAR_FUNC_ARG                4
 #define BP_VAR_UNSET           5
 
-/* Bottom 3 bits are the type, top bits are arg num for BP_VAR_FUNC_ARG */
-#define BP_VAR_SHIFT 3
-#define BP_VAR_MASK  7
-
-
 #define ZEND_INTERNAL_FUNCTION                         1
 #define ZEND_USER_FUNCTION                                     2
 #define ZEND_OVERLOADED_FUNCTION                       3
@@ -875,8 +879,6 @@ void zend_assert_valid_class_name(const zend_string *const_name);
 
 #define ZEND_ISSET                                 0x00000001
 
-#define ZEND_FETCH_ARG_MASK         0x0fffffff
-
 #define ZEND_LAST_CATCH                            0x00000001
 
 #define ZEND_FREE_ON_RETURN     (1<<0)
index 7714ecf852a22c7d32dfaa1357017a7cce853919..9e4f0baf0a31f93072e9cb6e75d79f698762d2a2 100644 (file)
@@ -1228,6 +1228,7 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(EXECUTE_DATA_D)
                                                        break;
                                                case ZEND_SEND_REF:
                                                case ZEND_SEND_VAR_EX:
+                                               case ZEND_SEND_FUNC_ARG:
                                                        msg = "Only variables can be passed by reference";
                                                        break;
                                                case ZEND_FE_RESET_RW:
@@ -2491,6 +2492,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o
                                        case ZEND_SEND_VAL_EX:
                                        case ZEND_SEND_VAR:
                                        case ZEND_SEND_VAR_EX:
+                                       case ZEND_SEND_FUNC_ARG:
                                        case ZEND_SEND_REF:
                                        case ZEND_SEND_VAR_NO_REF:
                                        case ZEND_SEND_VAR_NO_REF_EX:
index fa450b1427bd308ffc27d82a69ba4c5026faa8b5..3f34100ba721f7802785ea5844658befb3c1d83a 100644 (file)
@@ -1485,11 +1485,11 @@ ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
        ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_RW);
 }
 
-ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ARG_NUM)
+ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value & ZEND_FETCH_ARG_MASK, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_W);
        } else {
                ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_R);
@@ -1554,11 +1554,11 @@ ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, CONST|TMPVAR|CV, UNUSED|CLASS_FE
        ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_RW);
 }
 
-ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, NUM)
+ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR)
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_W);
        } else {
                ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_R);
@@ -1659,11 +1659,11 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
-ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, NUM)
+ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -1946,11 +1946,11 @@ ZEND_VM_C_LABEL(fetch_obj_is_no_object):
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
-ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, NUM)
+ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -4362,6 +4362,68 @@ ZEND_VM_C_LABEL(send_var_by_ref):
        ZEND_VM_NEXT_OPCODE();
 }
 
+ZEND_VM_HOT_HANDLER(100, ZEND_CHECK_FUNC_ARG, UNUSED, NUM, SPEC(QUICK_ARG))
+{
+       USE_OPLINE
+       uint32_t arg_num = opline->op2.num;
+
+       if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
+               if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
+                       ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+               } else {
+                       ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+               }
+       } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
+               ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+       } else {
+               ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+       }
+       ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HOT_HANDLER(185, ZEND_SEND_FUNC_ARG, VAR, NUM)
+{
+       USE_OPLINE
+       zval *varptr, *arg;
+       zend_free_op free_op1;
+
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
+               ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);
+       }
+
+       varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+       if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) {
+               SAVE_OPLINE();
+               GET_OP1_UNDEF_CV(varptr, BP_VAR_R);
+               arg = ZEND_CALL_VAR(EX(call), opline->result.var);
+               ZVAL_NULL(arg);
+               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       }
+
+       arg = ZEND_CALL_VAR(EX(call), opline->result.var);
+
+       if (OP1_TYPE == IS_CV) {
+               ZVAL_OPT_DEREF(varptr);
+               ZVAL_COPY(arg, varptr);
+       } else /* if (OP1_TYPE == IS_VAR) */ {
+               if (UNEXPECTED(Z_ISREF_P(varptr))) {
+                       zend_refcounted *ref = Z_COUNTED_P(varptr);
+
+                       varptr = Z_REFVAL_P(varptr);
+                       ZVAL_COPY_VALUE(arg, varptr);
+                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                               efree_size(ref, sizeof(zend_reference));
+                       } else if (Z_OPT_REFCOUNTED_P(arg)) {
+                               Z_ADDREF_P(arg);
+                       }
+               } else {
+                       ZVAL_COPY_VALUE(arg, varptr);
+               }
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY)
 {
        USE_OPLINE
index 8e42c33365eba3c166efa2d5ecaf6f22049291ca..cc67f61dffa75d5b735918d0d8addd3a60320033 100644 (file)
@@ -4683,7 +4683,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -4754,7 +4754,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -4977,7 +4977,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -6961,7 +6961,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -7186,7 +7186,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -8217,7 +8217,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -8669,7 +8669,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUS
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value & ZEND_FETCH_ARG_MASK, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -8736,7 +8736,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -8757,7 +8757,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -10100,7 +10100,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -10323,7 +10323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -13795,7 +13795,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -16243,7 +16243,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -16604,7 +16604,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNU
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value & ZEND_FETCH_ARG_MASK, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -16673,7 +16673,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -19058,7 +19058,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CO
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -19085,7 +19085,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CO
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -19495,7 +19495,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TM
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -19522,7 +19522,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TM
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -20069,7 +20069,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UN
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -20498,7 +20498,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -20525,7 +20525,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -21619,6 +21619,49 @@ send_var_by_ref:
        ZEND_VM_NEXT_OPCODE();
 }
 
+static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zval *varptr, *arg;
+       zend_free_op free_op1;
+
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
+               ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
+       }
+
+       varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC);
+       if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) {
+               SAVE_OPLINE();
+               GET_OP1_UNDEF_CV(varptr, BP_VAR_R);
+               arg = ZEND_CALL_VAR(EX(call), opline->result.var);
+               ZVAL_NULL(arg);
+               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       }
+
+       arg = ZEND_CALL_VAR(EX(call), opline->result.var);
+
+       if (IS_VAR == IS_CV) {
+               ZVAL_OPT_DEREF(varptr);
+               ZVAL_COPY(arg, varptr);
+       } else /* if (IS_VAR == IS_VAR) */ {
+               if (UNEXPECTED(Z_ISREF_P(varptr))) {
+                       zend_refcounted *ref = Z_COUNTED_P(varptr);
+
+                       varptr = Z_REFVAL_P(varptr);
+                       ZVAL_COPY_VALUE(arg, varptr);
+                       if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+                               efree_size(ref, sizeof(zend_reference));
+                       } else if (Z_OPT_REFCOUNTED_P(arg)) {
+                               Z_ADDREF_P(arg);
+                       }
+               } else {
+                       ZVAL_COPY_VALUE(arg, varptr);
+               }
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -23369,7 +23412,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CO
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -23458,7 +23501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CO
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -25810,7 +25853,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TM
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -25899,7 +25942,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TM
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -28063,7 +28106,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -29665,7 +29708,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -29754,7 +29797,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -31540,6 +31583,44 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_
 }
 
 
+static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       uint32_t arg_num = opline->op2.num;
+
+       if (EXPECTED(0)) {
+               if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
+                       ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+               } else {
+                       ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+               }
+       } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
+               ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+       } else {
+               ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+       }
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       uint32_t arg_num = opline->op2.num;
+
+       if (EXPECTED(1)) {
+               if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
+                       ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+               } else {
+                       ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+               }
+       } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
+               ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+       } else {
+               ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
+       }
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -32295,7 +32376,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -34165,7 +34246,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -36608,7 +36689,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -40897,7 +40978,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -41002,7 +41083,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CON
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_CV & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -41287,7 +41368,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CON
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_CV & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -44897,7 +44978,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_CV & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -45184,7 +45265,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_CV & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -47242,7 +47323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -48026,7 +48107,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value & ZEND_FETCH_ARG_MASK, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -48093,7 +48174,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
        } else {
                ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
@@ -48148,7 +48229,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_CV & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -50640,7 +50721,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
         if ((IS_CV & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
             zend_throw_error(NULL, "Cannot use temporary expression in write context");
@@ -50925,7 +51006,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_
 {
        USE_OPLINE
 
-       if (zend_is_by_ref_func_arg_fetch(opline->extended_value, EX(call)->func)) {
+       if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
                /* Behave like FETCH_OBJ_W */
                if ((IS_CV & (IS_CONST|IS_TMP_VAR))) {
                        SAVE_OPLINE();
@@ -54946,6 +55027,8 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        (void*)&&ZEND_NULL_LABEL,
                        (void*)&&ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_LABEL,
                        (void*)&&ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_LABEL,
+                       (void*)&&ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_LABEL,
+                       (void*)&&ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_QUICK_LABEL,
                        (void*)&&ZEND_EXT_STMT_SPEC_LABEL,
                        (void*)&&ZEND_EXT_FCALL_BEGIN_SPEC_LABEL,
                        (void*)&&ZEND_EXT_FCALL_END_SPEC_LABEL,
@@ -55916,6 +55999,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        (void*)&&ZEND_BIND_LEXICAL_SPEC_TMP_CV_LABEL,
                        (void*)&&ZEND_BIND_STATIC_SPEC_CV_CONST_LABEL,
                        (void*)&&ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_LABEL,
+                       (void*)&&ZEND_SEND_FUNC_ARG_SPEC_VAR_LABEL,
                        (void*)&&ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_LABEL,
                        (void*)&&ZEND_SWITCH_LONG_SPEC_CONST_CONST_LABEL,
                        (void*)&&ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_LABEL,
@@ -58477,6 +58561,9 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_VAR_QUICK):
                                ZEND_SEND_VAR_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_SEND_FUNC_ARG_SPEC_VAR):
+                               ZEND_SEND_FUNC_ARG_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_SEND_USER_SPEC_VAR):
                                ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
@@ -59239,6 +59326,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED):
                                ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_CHECK_FUNC_ARG_SPEC_UNUSED):
+                               ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_QUICK):
+                               ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_NEW_SPEC_UNUSED):
                                ZEND_NEW_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
@@ -62831,6 +62924,8 @@ void zend_init_opcodes_handlers(void)
                ZEND_NULL_HANDLER,
                ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER,
                ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER,
+               ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_HANDLER,
+               ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_QUICK_HANDLER,
                ZEND_EXT_STMT_SPEC_HANDLER,
                ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
                ZEND_EXT_FCALL_END_SPEC_HANDLER,
@@ -63801,6 +63896,7 @@ void zend_init_opcodes_handlers(void)
                ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER,
                ZEND_BIND_STATIC_SPEC_CV_CONST_HANDLER,
                ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER,
+               ZEND_SEND_FUNC_ARG_SPEC_VAR_HANDLER,
                ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER,
                ZEND_SWITCH_LONG_SPEC_CONST_CONST_HANDLER,
                ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_HANDLER,
@@ -64865,106 +64961,106 @@ void zend_init_opcodes_handlers(void)
                1957 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                1982 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                2007,
-               3939,
-               2008,
-               2009,
+               2008 | SPEC_RULE_QUICK_ARG,
                2010,
                2011,
                2012,
                2013,
                2014,
-               2015 | SPEC_RULE_OP1,
-               2020 | SPEC_RULE_OP2,
-               2025 | SPEC_RULE_OP1,
-               2030 | SPEC_RULE_OP1,
-               2035 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2060 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2085 | SPEC_RULE_OP1,
-               2090 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2115 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG,
-               2125 | SPEC_RULE_OP1,
-               2130 | SPEC_RULE_OP2,
-               2135,
-               2136 | SPEC_RULE_OP1,
-               2141 | SPEC_RULE_OP1,
-               2146,
-               2147 | SPEC_RULE_OP1,
-               2152 | SPEC_RULE_OP1,
-               2157 | SPEC_RULE_OP1,
-               2162,
-               2163,
-               2164 | SPEC_RULE_OP2,
-               2169 | SPEC_RULE_RETVAL,
+               2015,
+               2016,
+               2017 | SPEC_RULE_OP1,
+               2022 | SPEC_RULE_OP2,
+               2027 | SPEC_RULE_OP1,
+               2032 | SPEC_RULE_OP1,
+               2037 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2062 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2087 | SPEC_RULE_OP1,
+               2092 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2117 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG,
+               2127 | SPEC_RULE_OP1,
+               2132 | SPEC_RULE_OP2,
+               2137,
+               2138 | SPEC_RULE_OP1,
+               2143 | SPEC_RULE_OP1,
+               2148,
+               2149 | SPEC_RULE_OP1,
+               2154 | SPEC_RULE_OP1,
+               2159 | SPEC_RULE_OP1,
+               2164,
+               2165,
+               2166 | SPEC_RULE_OP2,
                2171 | SPEC_RULE_RETVAL,
                2173 | SPEC_RULE_RETVAL,
-               2175 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2200 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2225 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2250 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2275 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_OP_DATA,
-               2400,
-               2401 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2426,
-               2427,
+               2175 | SPEC_RULE_RETVAL,
+               2177 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2202 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2227 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2252 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2277 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_OP_DATA,
+               2402,
+               2403 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                2428,
-               2429 | SPEC_RULE_OP1,
-               2434,
-               2435,
+               2429,
+               2430,
+               2431 | SPEC_RULE_OP1,
                2436,
                2437,
-               2438 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_OP_DATA,
-               2563 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2588,
-               2589,
+               2438,
+               2439,
+               2440 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_OP_DATA,
+               2565 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                2590,
-               2591 | SPEC_RULE_OP1,
-               2596,
-               2597,
+               2591,
+               2592,
+               2593 | SPEC_RULE_OP1,
                2598,
                2599,
                2600,
                2601,
                2602,
-               2603 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2628 | SPEC_RULE_OP1,
-               2633,
-               2634,
+               2603,
+               2604,
+               2605 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2630 | SPEC_RULE_OP1,
                2635,
                2636,
-               2637 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2662 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_DIM_OBJ,
-               2737,
-               2738 | SPEC_RULE_OP1,
-               2743 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2768,
-               2769,
-               2770 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2795 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2820 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2845 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2870 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2895 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2920 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2945 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               2970 | SPEC_RULE_OP1,
-               2975,
-               2976,
+               2637,
+               2638,
+               2639 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2664 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_DIM_OBJ,
+               2739,
+               2740 | SPEC_RULE_OP1,
+               2745 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2770,
+               2771,
+               2772 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2797 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2822 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2847 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2872 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2897 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2922 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2947 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               2972 | SPEC_RULE_OP1,
                2977,
-               3939,
                2978,
-               2979 | SPEC_RULE_OP1,
-               2984 | SPEC_RULE_OP1,
-               2989 | SPEC_RULE_OP1,
-               2994 | SPEC_RULE_OP1,
-               2999 | SPEC_RULE_OP1,
-               3004,
-               3005 | SPEC_RULE_OP1,
-               3010,
-               3011 | SPEC_RULE_OP1,
-               3016,
-               3017,
-               3018 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               3939
+               2979,
+               2980,
+               2981,
+               2982 | SPEC_RULE_OP1,
+               2987 | SPEC_RULE_OP1,
+               2992 | SPEC_RULE_OP1,
+               2997 | SPEC_RULE_OP1,
+               3002 | SPEC_RULE_OP1,
+               3007,
+               3008 | SPEC_RULE_OP1,
+               3013,
+               3014 | SPEC_RULE_OP1,
+               3019,
+               3020,
+               3021 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               3942
        };
 #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
        zend_opcode_handler_funcs = labels;
@@ -65152,7 +65248,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3044 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
+                               spec = 3047 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
                                if (op->op1_type < op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -65160,7 +65256,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3069 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
+                               spec = 3072 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
                                if (op->op1_type < op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -65168,7 +65264,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3094 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
+                               spec = 3097 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
                                if (op->op1_type < op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -65179,17 +65275,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3119 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3122 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                        } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3144 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3147 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                        } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3169 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3172 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                        }
                        break;
                case ZEND_MUL:
@@ -65200,17 +65296,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3194 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
+                               spec = 3197 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
                        } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3219 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
+                               spec = 3222 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
                        } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3244 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
+                               spec = 3247 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
                        }
                        break;
                case ZEND_IS_EQUAL:
@@ -65221,12 +65317,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3269 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
+                               spec = 3272 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
                        } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3344 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
+                               spec = 3347 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
                        }
                        break;
                case ZEND_IS_NOT_EQUAL:
@@ -65237,12 +65333,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3419 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
+                               spec = 3422 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
                        } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3494 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
+                               spec = 3497 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
                        }
                        break;
                case ZEND_IS_SMALLER:
@@ -65250,12 +65346,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3569 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 3572 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                        } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3644 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 3647 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                        }
                        break;
                case ZEND_IS_SMALLER_OR_EQUAL:
@@ -65263,80 +65359,80 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3719 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 3722 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                        } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
                                if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
                                        break;
                                }
-                               spec = 3794 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 3797 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                        }
                        break;
                case ZEND_QM_ASSIGN:
                        if (op1_info == MAY_BE_DOUBLE) {
-                               spec = 3887 | SPEC_RULE_OP1;
+                               spec = 3890 | SPEC_RULE_OP1;
                        } else if (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))) {
-                               spec = 3892 | SPEC_RULE_OP1;
+                               spec = 3895 | SPEC_RULE_OP1;
                        }
                        break;
                case ZEND_PRE_INC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 3869 | SPEC_RULE_RETVAL;
+                               spec = 3872 | SPEC_RULE_RETVAL;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 3871 | SPEC_RULE_RETVAL;
+                               spec = 3874 | SPEC_RULE_RETVAL;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 3873 | SPEC_RULE_RETVAL;
+                               spec = 3876 | SPEC_RULE_RETVAL;
                        }
                        break;
                case ZEND_PRE_DEC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 3875 | SPEC_RULE_RETVAL;
+                               spec = 3878 | SPEC_RULE_RETVAL;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 3877 | SPEC_RULE_RETVAL;
+                               spec = 3880 | SPEC_RULE_RETVAL;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 3879 | SPEC_RULE_RETVAL;
+                               spec = 3882 | SPEC_RULE_RETVAL;
                        }
                        break;
                case ZEND_POST_INC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 3881;
+                               spec = 3884;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 3882;
+                               spec = 3885;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 3883;
+                               spec = 3886;
                        }
                        break;
                case ZEND_POST_DEC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 3884;
+                               spec = 3887;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 3885;
+                               spec = 3888;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 3886;
+                               spec = 3889;
                        }
                        break;
                case ZEND_JMP:
                        if (OP_JMP_ADDR(op, op->op1) > op) {
-                               spec = 3043;
+                               spec = 3046;
                        }
                        break;
                case ZEND_SEND_VAR_EX:
                        if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
-                               spec = 3927 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG;
+                               spec = 3930 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG;
                        }
                        break;
                case ZEND_FE_FETCH_R:
                        if (op->op2_type == IS_CV && (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) {
-                               spec = 3937 | SPEC_RULE_RETVAL;
+                               spec = 3940 | SPEC_RULE_RETVAL;
                        }
                        break;
                case ZEND_FETCH_DIM_R:
                        if (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) {
-                               spec = 3897 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3900 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                        }
                        break;
                case ZEND_SEND_VAR:
                        if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
-                               spec = 3922 | SPEC_RULE_OP1;
+                               spec = 3925 | SPEC_RULE_OP1;
                        }
                        break;
                case ZEND_BW_OR:
index 2c392b87609638dc9935d44b804d23e9a4ce9e11..d95a439c7e359b2eed2b5d78a60c9c090f930426 100644 (file)
@@ -73,7 +73,6 @@ $vm_op_flags = array(
 
        "ZEND_VM_EXT_VAR_FETCH"   => 1<<16,
        "ZEND_VM_EXT_ISSET"       => 1<<17,
-       "ZEND_VM_EXT_ARG_NUM"     => 1<<18,
        "ZEND_VM_EXT_ARRAY_INIT"  => 1<<19,
        "ZEND_VM_EXT_REF"         => 1<<20,
        "ZEND_VM_EXT_MASK"        => 0x0f000000,
@@ -128,7 +127,6 @@ $vm_ext_decode = array(
        "EVAL"                 => ZEND_VM_EXT_EVAL,
        "TYPE_MASK"            => ZEND_VM_EXT_TYPE_MASK,
        "ISSET"                => ZEND_VM_EXT_ISSET,
-       "ARG_NUM"              => ZEND_VM_EXT_ARG_NUM,
        "REF"                  => ZEND_VM_EXT_REF,
        "SRC"                  => ZEND_VM_EXT_SRC,
 );
index b01d7395d3c1018e24efe5e270a0491555f18cf7..7be1db00523b7fa58425e257d722573182c005e2 100644 (file)
@@ -122,7 +122,7 @@ static const char *zend_vm_opcodes_names[199] = {
        "ZEND_FETCH_OBJ_UNSET",
        "ZEND_FETCH_LIST_R",
        "ZEND_FETCH_CONSTANT",
-       NULL,
+       "ZEND_CHECK_FUNC_ARG",
        "ZEND_EXT_STMT",
        "ZEND_EXT_FCALL_BEGIN",
        "ZEND_EXT_FCALL_END",
@@ -207,7 +207,7 @@ static const char *zend_vm_opcodes_names[199] = {
        "ZEND_BIND_LEXICAL",
        "ZEND_BIND_STATIC",
        "ZEND_FETCH_THIS",
-       NULL,
+       "ZEND_SEND_FUNC_ARG",
        "ZEND_ISSET_ISEMPTY_THIS",
        "ZEND_SWITCH_LONG",
        "ZEND_SWITCH_STRING",
@@ -316,15 +316,15 @@ static uint32_t zend_vm_opcodes_flags[199] = {
        0x00010107,
        0x00000707,
        0x00000757,
-       0x00050107,
-       0x01006703,
-       0x01000753,
+       0x00010107,
+       0x00006703,
+       0x00000753,
        0x00010107,
        0x00000701,
        0x00000751,
        0x0000070b,
        0x00000391,
-       0x00000000,
+       0x00001001,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -401,7 +401,7 @@ static uint32_t zend_vm_opcodes_flags[199] = {
        0x00007307,
        0x00007307,
        0x00007307,
-       0x01007307,
+       0x00007307,
        0x00007307,
        0x00007307,
        0x00027307,
@@ -409,7 +409,7 @@ static uint32_t zend_vm_opcodes_flags[199] = {
        0x00100101,
        0x00100301,
        0x00000101,
-       0x00000000,
+       0x00001001,
        0x00000101,
        0x0300030b,
        0x0300030b,
index fc0cba498f8944575bb2125ad3ebe4e76a939cb5..d652c292ce3812ae4df7b69c44acfa570bf12365 100644 (file)
@@ -50,7 +50,6 @@
 #define ZEND_VM_OP_CONST_FETCH   0x00000090
 #define ZEND_VM_EXT_VAR_FETCH    0x00010000
 #define ZEND_VM_EXT_ISSET        0x00020000
-#define ZEND_VM_EXT_ARG_NUM      0x00040000
 #define ZEND_VM_EXT_ARRAY_INIT   0x00080000
 #define ZEND_VM_EXT_REF          0x00100000
 #define ZEND_VM_EXT_MASK         0x0f000000
@@ -174,6 +173,7 @@ END_EXTERN_C()
 #define ZEND_FETCH_OBJ_UNSET                  97
 #define ZEND_FETCH_LIST_R                     98
 #define ZEND_FETCH_CONSTANT                   99
+#define ZEND_CHECK_FUNC_ARG                  100
 #define ZEND_EXT_STMT                        101
 #define ZEND_EXT_FCALL_BEGIN                 102
 #define ZEND_EXT_FCALL_END                   103
@@ -258,6 +258,7 @@ END_EXTERN_C()
 #define ZEND_BIND_LEXICAL                    182
 #define ZEND_BIND_STATIC                     183
 #define ZEND_FETCH_THIS                      184
+#define ZEND_SEND_FUNC_ARG                   185
 #define ZEND_ISSET_ISEMPTY_THIS              186
 #define ZEND_SWITCH_LONG                     187
 #define ZEND_SWITCH_STRING                   188
index 2696a64879eb11f93fcf57fa3379a58b05084e18..32de6ba35c5352a7267e765ffd3858b381062c9e 100644 (file)
@@ -40,6 +40,7 @@ typedef struct _optimizer_call_info {
        zend_function *func;
        zend_op       *opline;
        zend_bool      try_inline;
+       uint32_t       func_arg_num;
 } optimizer_call_info;
 
 static void zend_delete_call_instructions(zend_op *opline)
@@ -176,6 +177,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                        case ZEND_INIT_DYNAMIC_CALL:
                        case ZEND_INIT_USER_CALL:
                                call_stack[call].opline = opline;
+                               call_stack[call].func_arg_num = (uint32_t)-1;
                                call++;
                                break;
                        case ZEND_DO_FCALL:
@@ -219,14 +221,15 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                                call_stack[call].func = NULL;
                                call_stack[call].opline = NULL;
                                call_stack[call].try_inline = 0;
+                               call_stack[call].func_arg_num = (uint32_t)-1;
                                break;
                        case ZEND_FETCH_FUNC_ARG:
                        case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
                        case ZEND_FETCH_OBJ_FUNC_ARG:
                        case ZEND_FETCH_DIM_FUNC_ARG:
                                if (call_stack[call - 1].func) {
-                                       if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
-                                               opline->extended_value &= ZEND_FETCH_TYPE_MASK;
+                                       ZEND_ASSERT(call_stack[call - 1].func_arg_num != (uint32_t)-1);
+                                       if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, call_stack[call - 1].func_arg_num)) {
                                                if (opline->opcode != ZEND_FETCH_STATIC_PROP_FUNC_ARG) {
                                                        opline->opcode -= 9;
                                                } else {
@@ -241,7 +244,6 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                                                        break;
                                                }
 
-                                               opline->extended_value &= ZEND_FETCH_TYPE_MASK;
                                                if (opline->opcode != ZEND_FETCH_STATIC_PROP_FUNC_ARG) {
                                                        opline->opcode -= 12;
                                                } else {
@@ -260,8 +262,16 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                                        }
                                }
                                break;
+                       case ZEND_CHECK_FUNC_ARG:
+                               if (call_stack[call - 1].func) {
+                                       call_stack[call - 1].func_arg_num = opline->op2.num;
+                                       MAKE_NOP(opline);
+                               }
+                               break;
                        case ZEND_SEND_VAR_EX:
+                       case ZEND_SEND_FUNC_ARG:
                                if (call_stack[call - 1].func) {
+                                       call_stack[call - 1].func_arg_num = (uint32_t)-1;
                                        if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
                                                opline->opcode = ZEND_SEND_REF;
                                        } else {
index bf6d57f03081edcbf3bd630c8ed2d1a19102c493..1b2623c30752a675a2fd653d04c2e4bf4e452f81 100644 (file)
@@ -228,6 +228,7 @@ static zend_bool can_replace_op1(
                case ZEND_UNSET_OBJ:
                case ZEND_SEND_REF:
                case ZEND_SEND_VAR_EX:
+               case ZEND_SEND_FUNC_ARG:
                case ZEND_SEND_UNPACK:
                case ZEND_SEND_ARRAY:
                case ZEND_SEND_USER:
index 886a7939716fbdf1e6d81e82507d4c3924ef3922..a23e9ead6378130dd02d37859901c4a131f3a537 100644 (file)
@@ -152,6 +152,7 @@ int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_f
                        case ZEND_SEND_VAR:
                        case ZEND_SEND_VAL_EX:
                        case ZEND_SEND_VAR_EX:
+                       case ZEND_SEND_FUNC_ARG:
                        case ZEND_SEND_REF:
                        case ZEND_SEND_VAR_NO_REF:
                        case ZEND_SEND_VAR_NO_REF_EX:
index d750c136a294fc4459249d439600f30af1964b98..224ea56167a1f08e118e22c95589f0bbb5763bb2 100644 (file)
@@ -95,6 +95,7 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg
                                        case ZEND_BIND_GLOBAL:
                                        case ZEND_BIND_STATIC:
                                        case ZEND_SEND_VAR_EX:
+                                       case ZEND_SEND_FUNC_ARG:
                                        case ZEND_SEND_REF:
                                        case ZEND_SEND_VAR_NO_REF:
                                        case ZEND_SEND_VAR_NO_REF_EX:
index 0724dd52e2dd384883b6c2230e550e71054b93fb..22e149ae5539dd60b681817a3e7ee34543235060 100644 (file)
@@ -563,16 +563,12 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *
                }
        } else {
                if (ZEND_VM_EXT_VAR_FETCH & flags) {
-                       switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
-                               case ZEND_FETCH_GLOBAL:
-                                       fprintf(stderr, " (global)");
-                                       break;
-                               case ZEND_FETCH_LOCAL:
-                                       fprintf(stderr, " (local)");
-                                       break;
-                               case ZEND_FETCH_GLOBAL_LOCK:
-                                       fprintf(stderr, " (global+lock)");
-                                       break;
+                       if (opline->extended_value & ZEND_FETCH_GLOBAL) {
+                               fprintf(stderr, " (global)");
+                       } else if (opline->extended_value & ZEND_FETCH_LOCAL) {
+                               fprintf(stderr, " (local)");
+                       } else if (opline->extended_value & ZEND_FETCH_GLOBAL_LOCK) {
+                               fprintf(stderr, " (global+lock)");
                        }
                }
                if (ZEND_VM_EXT_ISSET & flags) {
@@ -582,9 +578,6 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *
                                fprintf(stderr, " (empty)");
                        }
                }
-               if (ZEND_VM_EXT_ARG_NUM & flags) {
-                       fprintf(stderr, " %u", opline->extended_value & ZEND_FETCH_ARG_MASK);
-               }
                if (ZEND_VM_EXT_ARRAY_INIT & flags) {
                        fprintf(stderr, " %u", opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT);
                        if (!(opline->extended_value & ZEND_ARRAY_NOT_PACKED)) {
index fef99bc0538d555462c3a2ac4eabd1c517928d00..26ef8b82a9e353a1b554f04c2ecd4d6f5c001905 100644 (file)
@@ -2721,6 +2721,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
                        }
                        break;
                case ZEND_SEND_VAR_EX:
+               case ZEND_SEND_FUNC_ARG:
                        if (ssa_ops[i].op1_def >= 0) {
                                tmp = (t1 & MAY_BE_UNDEF)|MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
@@ -3093,6 +3094,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
                                                        tmp |= MAY_BE_ARRAY_OF_OBJECT;
                                                        break;
                                                case ZEND_SEND_VAR_EX:
+                                               case ZEND_SEND_FUNC_ARG:
                                                case ZEND_SEND_VAR_NO_REF:
                                                case ZEND_SEND_VAR_NO_REF_EX:
                                                case ZEND_SEND_REF:
@@ -4042,6 +4044,7 @@ int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa
                                case ZEND_SEND_VAL_EX:
                                case ZEND_SEND_VAR:
                                case ZEND_SEND_VAR_EX:
+                               case ZEND_SEND_FUNC_ARG:
                                case ZEND_SEND_VAR_NO_REF:
                                case ZEND_SEND_VAR_NO_REF_EX:
                                case ZEND_SEND_REF:
@@ -4091,6 +4094,7 @@ int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa
                case ZEND_SEND_VAL:
                case ZEND_SEND_REF:
                case ZEND_SEND_VAR_EX:
+               case ZEND_SEND_FUNC_ARG:
                case ZEND_FREE:
                case ZEND_SEPARATE:
                case ZEND_TYPE_CHECK:
index a7d463030f54ceb781c5274e19e40b578c147691..f9b21ff19ede46b62ad2105885a09610b4e29a82 100644 (file)
@@ -265,6 +265,7 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
                        zval_ptr_dtor_nogc(val);
                        return 1;
                case ZEND_SEND_VAR_EX:
+               case ZEND_SEND_FUNC_ARG:
                case ZEND_FETCH_DIM_W:
                case ZEND_FETCH_DIM_RW:
                case ZEND_FETCH_DIM_FUNC_ARG:
@@ -593,6 +594,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                        opline->opcode = ZEND_SEND_VAL;
                                        break;
                                case ZEND_SEND_VAR_EX:
+                               case ZEND_SEND_FUNC_ARG:
                                        opline->extended_value = 0;
                                        opline->opcode = ZEND_SEND_VAL_EX;
                                        break;
index 45e6721216e029969d70036f33e94fa1eae0598b..a18f4a875c09d3a58bd351a85798e97aaee023aa 100644 (file)
@@ -680,6 +680,7 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags,
                                case ZEND_SEND_VAR_NO_REF:
                                case ZEND_SEND_VAR_NO_REF_EX:
                                case ZEND_SEND_VAR_EX:
+                               case ZEND_SEND_FUNC_ARG:
                                case ZEND_SEND_REF:
                                case ZEND_SEND_UNPACK:
                                case ZEND_FE_RESET_RW: