diff options
author | Dmitry Stogov <dmitry@zend.com> | 2018-02-05 19:40:06 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2018-02-05 19:40:06 +0300 |
commit | 3a794d39f081f73b2204aed8b80163a197ab41c3 (patch) | |
tree | 90af4978f502d85b1a1ac1e1e72ebeaf9e65d6bc | |
parent | 7416562ab0c1062722c43c6b55d38e1a79f217cb (diff) | |
download | php-git-3a794d39f081f73b2204aed8b80163a197ab41c3.tar.gz |
Avoid repeatable ARG_SHOULD_BE_SENT_BY_REF() checks in FETCH_*FUNC_ARG and following SEND_VAR_EX. Perform the check once in a new CHECK_FUNC_ARG opcode and reuse in the following FETCH_*FUNC_ARG and SEND_FUNC_ARG (SEND_VAR_EX replacement).
-rw-r--r-- | Zend/zend_compile.c | 23 | ||||
-rw-r--r-- | Zend/zend_compile.h | 16 | ||||
-rw-r--r-- | Zend/zend_execute.c | 2 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 78 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 414 | ||||
-rw-r--r-- | Zend/zend_vm_gen.php | 2 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.c | 16 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.h | 3 | ||||
-rw-r--r-- | ext/opcache/Optimizer/optimize_func_calls.c | 16 | ||||
-rw-r--r-- | ext/opcache/Optimizer/sccp.c | 1 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_call_graph.c | 1 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_dfg.c | 1 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_dump.c | 19 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_inference.c | 4 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 2 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_ssa.c | 1 |
16 files changed, 393 insertions, 206 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0b4941e1f4..3d9b2e77c6 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index e26d6c7cc4..65a03e6b0e 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 7714ecf852..9e4f0baf0a 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index fa450b1427..3f34100ba7 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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 diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 8e42c33365..cc67f61dff 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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: diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 2c392b8760..d95a439c7e 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -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, ); diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index b01d7395d3..7be1db0052 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -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, diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index fc0cba498f..d652c292ce 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -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 diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c index 2696a64879..32de6ba35c 100644 --- a/ext/opcache/Optimizer/optimize_func_calls.c +++ b/ext/opcache/Optimizer/optimize_func_calls.c @@ -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 { diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c index bf6d57f030..1b2623c307 100644 --- a/ext/opcache/Optimizer/sccp.c +++ b/ext/opcache/Optimizer/sccp.c @@ -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: diff --git a/ext/opcache/Optimizer/zend_call_graph.c b/ext/opcache/Optimizer/zend_call_graph.c index 886a793971..a23e9ead63 100644 --- a/ext/opcache/Optimizer/zend_call_graph.c +++ b/ext/opcache/Optimizer/zend_call_graph.c @@ -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: diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c index d750c136a2..224ea56167 100644 --- a/ext/opcache/Optimizer/zend_dfg.c +++ b/ext/opcache/Optimizer/zend_dfg.c @@ -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: diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 0724dd52e2..22e149ae55 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -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)) { diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index fef99bc053..26ef8b82a9 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -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: diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index a7d463030f..f9b21ff19e 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -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; diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c index 45e6721216..a18f4a875c 100644 --- a/ext/opcache/Optimizer/zend_ssa.c +++ b/ext/opcache/Optimizer/zend_ssa.c @@ -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: |