diff options
Diffstat (limited to 'Zend/zend_vm_execute.h')
| -rw-r--r-- | Zend/zend_vm_execute.h | 17628 |
1 files changed, 9391 insertions, 8237 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index dc49bcd434..9d7eae0311 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -316,6 +316,7 @@ static zend_uchar zend_user_opcodes[256] = {0, #define SPEC_RULE_SMART_BRANCH 0x00200000 #define SPEC_RULE_COMMUTATIVE 0x00800000 #define SPEC_RULE_ISSET 0x01000000 +#define SPEC_RULE_OBSERVER 0x02000000 static const uint32_t *zend_spec_handlers; static const void * const *zend_opcode_handlers; @@ -391,13 +392,6 @@ static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); -#undef OPLINE -#undef DCL_OPLINE -#undef USE_OPLINE -#undef LOAD_OPLINE -#undef LOAD_OPLINE_EX -#undef SAVE_OPLINE -#undef SAVE_OPLINE_EX #define DCL_OPLINE #ifdef ZEND_VM_IP_GLOBAL_REG # define OPLINE opline @@ -416,10 +410,8 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H # define SAVE_OPLINE() # define SAVE_OPLINE_EX() #endif -#undef HANDLE_EXCEPTION -#undef HANDLE_EXCEPTION_LEAVE -#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE() -#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE() +#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE() +#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_LEAVE() #if defined(ZEND_VM_FP_GLOBAL_REG) # define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE() # define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX() @@ -578,6 +570,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_right_ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -587,29 +580,19 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_hel if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret == 0, 1); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -619,29 +602,19 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) != 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret != 0, 1); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -651,29 +624,19 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_h if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) < 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret < 0, 1); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_or_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -683,25 +646,14 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_o if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_1); } if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) <= 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret <= 0, 1); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_or_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) @@ -767,16 +719,25 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_xor_helpe ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_not_helper_SPEC(zval *op_1 ZEND_OPCODE_HANDLER_ARGS_DC) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + bitwise_not_function(EX_VAR(opline->result.var), op_1); + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); zend_throw_error(NULL, "Using $this when not in object context"); - if ((opline+1)->opcode == ZEND_OP_DATA) { - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); - } - FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -797,7 +758,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN /* This helper actually never will receive IS_VAR as second op, and has the same handling for VAR and TMP in the first op, but for interoperability with the other binary_assign_op helpers, it is necessary to "include" it */ USE_OPLINE - zend_free_op free_op_data; zval *prop, *value; zend_property_info *prop_info; zend_reference *ref; @@ -805,13 +765,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN SAVE_OPLINE(); if (UNEXPECTED(zend_fetch_static_property_address(&prop, &prop_info, (opline+1)->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { - ZEND_ASSERT(EG(exception)); UNDEF_RESULT(); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); HANDLE_EXCEPTION(); } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (UNEXPECTED(Z_ISREF_P(prop))) { @@ -823,7 +782,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN } } - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { /* special case for typed properties */ zend_binary_assign_op_typed_prop(prop_info, prop, value OPLINE_CC EXECUTE_DATA_CC); } else { @@ -835,7 +794,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN ZVAL_COPY(EX_VAR(opline->result.var), prop); } - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_static_prop has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -853,7 +812,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_STATIC_PROP_SPEC_HANDL HANDLE_EXCEPTION(); } - zend_pre_incdec_property_zval(prop, prop_info->type ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_property_zval(prop, + ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -872,7 +832,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_STATIC_PROP_SPEC_HAND HANDLE_EXCEPTION(); } - zend_post_incdec_property_zval(prop, prop_info->type ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_property_zval(prop, + ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -943,8 +904,8 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_us SAVE_OPLINE(); zend_throw_error(NULL, "Cannot use temporary expression in write context"); - FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); - FREE_UNFETCHED_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -955,8 +916,8 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_us SAVE_OPLINE(); zend_throw_error(NULL, "Cannot use [] for reading"); - FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); - FREE_UNFETCHED_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -964,7 +925,6 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_us static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *prop, *value; zend_property_info *prop_info; @@ -978,7 +938,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); } else { @@ -996,7 +956,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *prop, *value; zend_property_info *prop_info; @@ -1008,11 +967,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT HANDLE_EXCEPTION(); } - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else { value = zend_assign_to_variable(prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } @@ -1028,7 +987,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *prop, *value; zend_property_info *prop_info; @@ -1040,11 +998,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT HANDLE_EXCEPTION(); } - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else { value = zend_assign_to_variable(prop, value, IS_VAR, EX_USES_STRICT_TYPES()); } @@ -1060,7 +1018,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *prop, *value; zend_property_info *prop_info; @@ -1074,7 +1031,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(prop_info->type)) { + if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); } else { @@ -1092,27 +1049,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *prop, *value_ptr; zend_property_info *prop_info; SAVE_OPLINE(); if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value & ~ZEND_RETURNS_FUNCTION, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); UNDEF_RESULT(); HANDLE_EXCEPTION(); } - value_ptr = get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, &free_op_data, BP_VAR_W); + value_ptr = get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, BP_VAR_W); - if ((opline+1)->op1_type == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - prop = &EG(uninitialized_zval); - } else if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { + if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { prop = &EG(uninitialized_zval); } - } else if (UNEXPECTED(prop_info->type)) { + } else if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr EXECUTE_DATA_CC); } else { zend_assign_to_variable_reference(prop, value_ptr); @@ -1122,7 +1076,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA ZVAL_COPY(EX_VAR(opline->result.var), prop); } - if (free_op_data) {zval_ptr_dtor_nogc(free_op_data);}; + if ((opline+1)->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));}; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -1132,7 +1086,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper uint32_t call_info = EX_CALL_INFO(); SAVE_OPLINE(); - if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED)) == 0)) { + if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); i_free_compiled_variables(execute_data); @@ -1165,6 +1119,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper zend_clean_and_cache_symbol_table(EX(symbol_table)); } + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(EX(extra_named_params)); + } + /* Free extra args before releasing the closure, * as that may free the op_array. */ zend_vm_stack_free_extra_args_ex(call_info, execute_data); @@ -1212,11 +1170,14 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper #ifdef ZEND_PREFER_RELOAD call_info = EX_CALL_INFO(); #endif - if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS))) { if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_clean_and_cache_symbol_table(EX(symbol_table)); } zend_vm_stack_free_extra_args_ex(call_info, execute_data); + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(EX(extra_named_params)); + } } if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); @@ -1263,6 +1224,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV call->prev_execute_data = execute_data; EG(current_execute_data) = call; +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1270,6 +1235,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1279,7 +1247,16 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); + + uint32_t call_info = ZEND_CALL_INFO(call); + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) { + if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_free_extra_named_params(call->extra_named_params); + } + zend_vm_stack_free_call_frame_ex(call_info, call); + } else { + EG(vm_stack_top) = (zval*)call; + } if (!0) { i_zval_ptr_dtor(ret); @@ -1308,6 +1285,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV call->prev_execute_data = execute_data; EG(current_execute_data) = call; +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1315,6 +1296,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1324,7 +1308,16 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV EG(current_execute_data) = execute_data; zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); + + uint32_t call_info = ZEND_CALL_INFO(call); + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) { + if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_free_extra_named_params(call->extra_named_params); + } + zend_vm_stack_free_call_frame_ex(call_info, call); + } else { + EG(vm_stack_top) = (zval*)call; + } if (!1) { i_zval_ptr_dtor(ret); @@ -1359,6 +1352,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); LOAD_OPLINE_EX(); + ZEND_VM_ENTER_EX(); } @@ -1382,6 +1376,32 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + ret = NULL; + if (RETURN_VALUE_USED(opline)) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + LOAD_OPLINE_EX(); + SAVE_OPLINE(); + zend_observer_fcall_begin(execute_data); + ZEND_VM_ENTER_EX(); } @@ -1406,10 +1426,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); LOAD_OPLINE_EX(); + ZEND_VM_ENTER_EX(); } else { zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (0) { + ret = NULL; + } if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { zend_deprecated_function(fbc); @@ -1426,15 +1450,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - UNDEF_RESULT(); - if (!0) { - ret = &retval; - ZVAL_UNDEF(ret); - } - goto fcall_by_name_end; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1443,6 +1461,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1454,7 +1475,16 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S fcall_by_name_end: zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); + + uint32_t call_info = ZEND_CALL_INFO(call); + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) { + if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_free_extra_named_params(call->extra_named_params); + } + zend_vm_stack_free_call_frame_ex(call_info, call); + } else { + EG(vm_stack_top) = (zval*)call; + } if (!0) { i_zval_ptr_dtor(ret); @@ -1490,10 +1520,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); LOAD_OPLINE_EX(); + ZEND_VM_ENTER_EX(); } else { zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (0) { + ret = NULL; + } if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { zend_deprecated_function(fbc); @@ -1510,15 +1544,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - UNDEF_RESULT(); - if (!1) { - ret = &retval; - ZVAL_UNDEF(ret); - } - goto fcall_by_name_end; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1527,6 +1555,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1538,7 +1569,16 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S fcall_by_name_end: zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); + + uint32_t call_info = ZEND_CALL_INFO(call); + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) { + if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_free_extra_named_params(call->extra_named_params); + } + zend_vm_stack_free_call_frame_ex(call_info, call); + } else { + EG(vm_stack_top) = (zval*)call; + } if (!1) { i_zval_ptr_dtor(ret); @@ -1553,33 +1593,110 @@ fcall_by_name_end: ZEND_VM_CONTINUE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; - zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { - zend_abstract_method(fbc); -fcall_except: - UNDEF_RESULT(); - if (!0) { - ret = &retval; - ZVAL_UNDEF(ret); - } - goto fcall_end; - } else { + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + ret = NULL; + if (RETURN_VALUE_USED(opline)) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + LOAD_OPLINE_EX(); + SAVE_OPLINE(); + zend_observer_fcall_begin(execute_data); + + ZEND_VM_ENTER_EX(); + } else { + zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (1) { + ret = NULL; + } + + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { zend_deprecated_function(fbc); if (UNEXPECTED(EG(exception) != NULL)) { - goto fcall_except; + UNDEF_RESULT(); + if (!RETURN_VALUE_USED(opline)) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_by_name_end; } } + + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + fbc->internal_function.handler(call, ret); + +#if ZEND_DEBUG + if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } +#endif + + EG(current_execute_data) = execute_data; + +fcall_by_name_end: + zend_vm_stack_free_args(call); + + uint32_t call_info = ZEND_CALL_INFO(call); + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) { + if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_free_extra_named_params(call->extra_named_params); + } + zend_vm_stack_free_call_frame_ex(call_info, call); + } else { + EG(vm_stack_top) = (zval*)call; + } + + if (!RETURN_VALUE_USED(opline)) { + i_zval_ptr_dtor(ret); + } + } + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); } + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { ret = NULL; @@ -1593,22 +1710,42 @@ fcall_except: if (EXPECTED(zend_execute_ex == execute_ex)) { LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } else { SAVE_OPLINE_EX(); + execute_data = EX(prev_execute_data); LOAD_OPLINE(); ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { + zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (0) { + ret = NULL; + } + + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_deprecated_function(fbc); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!0) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_end; + } + } + call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - goto fcall_except; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1622,6 +1759,9 @@ fcall_except: #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1633,21 +1773,12 @@ fcall_except: fcall_end: zend_vm_stack_free_args(call); - if (!0) { - i_zval_ptr_dtor(ret); - } - } else { /* ZEND_OVERLOADED_FUNCTION */ - ret = 0 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); } if (!0) { - zval_ptr_dtor(ret); + i_zval_ptr_dtor(ret); } } @@ -1671,27 +1802,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; - zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; - if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { - zend_abstract_method(fbc); -fcall_except: - UNDEF_RESULT(); - if (!1) { - ret = &retval; - ZVAL_UNDEF(ret); - } - goto fcall_end; - } else { - zend_deprecated_function(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - goto fcall_except; - } - } - } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { ret = NULL; @@ -1705,22 +1818,42 @@ fcall_except: if (EXPECTED(zend_execute_ex == execute_ex)) { LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } else { SAVE_OPLINE_EX(); + execute_data = EX(prev_execute_data); LOAD_OPLINE(); ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { + zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (0) { + ret = NULL; + } + + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_deprecated_function(fbc); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!1) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_end; + } + } + call->prev_execute_data = execute_data; EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - goto fcall_except; - } +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); @@ -1734,6 +1867,9 @@ fcall_except: #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -1745,21 +1881,120 @@ fcall_except: fcall_end: zend_vm_stack_free_args(call); + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } + if (!1) { i_zval_ptr_dtor(ret); } - } else { /* ZEND_OVERLOADED_FUNCTION */ - ret = 1 ? EX_VAR(opline->result.var) : &retval; + } + + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { + OBJ_RELEASE(Z_OBJ(call->This)); + } + + zend_vm_stack_free_call_frame(call); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + + ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + ret = NULL; + if (RETURN_VALUE_USED(opline)) { + ret = EX_VAR(opline->result.var); + } call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC); - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); + if (EXPECTED(zend_execute_ex == execute_ex)) { + LOAD_OPLINE_EX(); + SAVE_OPLINE(); + zend_observer_fcall_begin(execute_data); + ZEND_VM_ENTER_EX(); + } else { + SAVE_OPLINE_EX(); + zend_observer_fcall_begin(execute_data); + execute_data = EX(prev_execute_data); + LOAD_OPLINE(); + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + } + } else { + zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (1) { + ret = NULL; } - if (!1) { - zval_ptr_dtor(ret); + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_deprecated_function(fbc); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!RETURN_VALUE_USED(opline)) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_end; + } + } + + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(call, ret); + } else { + zend_execute_internal(call, ret); + } + +#if ZEND_DEBUG + if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } +#endif + + EG(current_execute_data) = execute_data; + +fcall_end: + zend_vm_stack_free_args(call); + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } + + if (!RETURN_VALUE_USED(opline)) { + i_zval_ptr_dtor(ret); } } @@ -1853,29 +2088,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_CREATE_SPEC_HANDLER( } } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_cannot_pass_by_ref_helper_SPEC(uint32_t _arg_num, zval *_arg ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE - zval *arg; - uint32_t arg_num = opline->op2.num; SAVE_OPLINE(); - zend_throw_error(NULL, "Cannot pass parameter %d by reference", arg_num); - FREE_UNFETCHED_OP(opline->op1_type, opline->op1.var); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_UNDEF(arg); + + zend_cannot_pass_by_reference(_arg_num); + FREE_OP(opline->op1_type, opline->op1.var); + ZVAL_UNDEF(_arg); HANDLE_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *args; - int arg_num; + uint32_t arg_num; SAVE_OPLINE(); - args = get_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + args = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1; send_again: @@ -1883,20 +2115,28 @@ send_again: HashTable *ht = Z_ARRVAL_P(args); zval *arg, *top; zend_string *name; + zend_bool have_named_params = 0; zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht)); + // TODO: Speed this up using a flag that specifies whether there are any ref parameters. if ((opline->op1_type & (IS_VAR|IS_CV)) && Z_REFCOUNT_P(args) > 1) { - uint32_t i; - int separate = 0; + uint32_t tmp_arg_num = arg_num; + bool separate = 0; /* check if any of arguments are going to be passed by reference */ - for (i = 0; i < zend_hash_num_elements(ht); i++) { - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) { + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { + if (UNEXPECTED(name)) { + void *cache_slot[2] = {NULL, NULL}; + tmp_arg_num = zend_get_arg_offset_by_name( + EX(call)->func, name, cache_slot) + 1; + } + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, tmp_arg_num)) { separate = 1; break; } - } + tmp_arg_num++; + } ZEND_HASH_FOREACH_END(); if (separate) { SEPARATE_ARRAY(args); ht = Z_ARRVAL_P(args); @@ -1904,13 +2144,26 @@ send_again: } ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { - if (name) { - zend_throw_error(NULL, "Cannot unpack array with string keys"); - FREE_OP(free_op1); - HANDLE_EXCEPTION(); + if (UNEXPECTED(name)) { + void *cache_slot[2] = {NULL, NULL}; + have_named_params = 1; + top = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot); + if (UNEXPECTED(!top)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } else { + if (have_named_params) { + zend_throw_error(NULL, + "Cannot use positional argument after named argument during unpacking"); + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + + top = ZEND_CALL_ARG(EX(call), arg_num); + ZEND_CALL_NUM_ARGS(EX(call))++; } - top = ZEND_CALL_ARG(EX(call), arg_num); if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { if (Z_ISREF_P(arg)) { Z_ADDREF_P(arg); @@ -1927,21 +2180,21 @@ send_again: ZVAL_COPY_DEREF(top, arg); } - ZEND_CALL_NUM_ARGS(EX(call))++; arg_num++; } ZEND_HASH_FOREACH_END(); } else if (EXPECTED(Z_TYPE_P(args) == IS_OBJECT)) { zend_class_entry *ce = Z_OBJCE_P(args); zend_object_iterator *iter; + zend_bool have_named_params = 0; if (!ce || !ce->get_iterator) { - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } else { iter = ce->get_iterator(ce, args, 0); if (UNEXPECTED(!iter)) { - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); if (!EG(exception)) { zend_throw_exception_ex( NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name) @@ -1966,6 +2219,7 @@ send_again: break; } + zend_string *name = NULL; if (iter->funcs->get_current_key) { zval key; iter->funcs->get_current_key(iter, &key); @@ -1974,32 +2228,61 @@ send_again: } if (UNEXPECTED(Z_TYPE(key) != IS_LONG)) { + if (UNEXPECTED(Z_TYPE(key) != IS_STRING)) { + zend_throw_error(NULL, + "Keys must be of type int|string during argument unpacking"); + zval_ptr_dtor(&key); + break; + } + + name = Z_STR_P(&key); + } + } + + if (UNEXPECTED(name)) { + void *cache_slot[2] = {NULL, NULL}; + have_named_params = 1; + top = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot); + if (UNEXPECTED(!top)) { + zend_string_release(name); + break; + } + + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + zend_error( + E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" + " by unpacking a Traversable, passing by-value instead", arg_num, + EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "", + EX(call)->func->common.scope ? "::" : "", + ZSTR_VAL(EX(call)->func->common.function_name) + ); + } + + ZVAL_COPY_DEREF(top, arg); + zend_string_release(name); + } else { + if (have_named_params) { zend_throw_error(NULL, - (Z_TYPE(key) == IS_STRING) ? - "Cannot unpack Traversable with string keys" : - "Cannot unpack Traversable with non-integer keys"); - zval_ptr_dtor(&key); + "Cannot use positional argument after named argument during unpacking"); break; } - } - if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - zend_error( - E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" - " by unpacking a Traversable, passing by-value instead", arg_num, - EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "", - EX(call)->func->common.scope ? "::" : "", - ZSTR_VAL(EX(call)->func->common.function_name) - ); - } + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + zend_error( + E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" + " by unpacking a Traversable, passing by-value instead", arg_num, + EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "", + EX(call)->func->common.scope ? "::" : "", + ZSTR_VAL(EX(call)->func->common.function_name) + ); + } - ZVAL_DEREF(arg); - Z_TRY_ADDREF_P(arg); - zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1); - top = ZEND_CALL_ARG(EX(call), arg_num); - ZVAL_COPY_VALUE(top, arg); - ZEND_CALL_NUM_ARGS(EX(call))++; + zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1); + top = ZEND_CALL_ARG(EX(call), arg_num); + ZVAL_COPY_DEREF(top, arg); + ZEND_CALL_NUM_ARGS(EX(call))++; + } iter->funcs->move_forward(iter); } @@ -2013,21 +2296,20 @@ send_again: if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *args; SAVE_OPLINE(); - args = get_zval_ptr(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + args = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) { if ((opline->op1_type & (IS_VAR|IS_CV)) && Z_ISREF_P(args)) { @@ -2036,27 +2318,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O goto send_array; } } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); - if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) { - OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func)); - } else if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_RELEASE_THIS) { - OBJ_RELEASE(Z_OBJ(EX(call)->This)); - } - EX(call)->func = (zend_function*)&zend_pass_function; - Z_OBJ(EX(call)->This) = NULL; - ZEND_CALL_INFO(EX(call)) &= ~(ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS); - FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); + zend_type_error("call_user_func_array(): Argument #2 ($args) must be of type array, %s given", zend_zval_type_name(args)); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); } else { uint32_t arg_num; HashTable *ht; zval *arg, *param; - send_array: ht = Z_ARRVAL_P(args); if (opline->op2_type != IS_UNUSED) { - zend_free_op free_op2; - zval *op2 = get_zval_ptr(opline->op2_type, opline->op2, &free_op2, BP_VAR_R); + /* We don't need to handle named params in this case, + * because array_slice() is called with $preserve_keys == false. */ + zval *op2 = get_zval_ptr(opline->op2_type, opline->op2, BP_VAR_R); uint32_t skip = opline->extended_value; uint32_t count = zend_hash_num_elements(ht); zend_long len = zval_get_long(op2); @@ -2105,12 +2381,30 @@ send_array: param++; } ZEND_HASH_FOREACH_END(); } - FREE_OP(free_op2); + FREE_OP(opline->op2_type, opline->op2.var); } else { + zend_string *name; + zend_bool have_named_params; zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht)); arg_num = 1; param = ZEND_CALL_ARG(EX(call), 1); - ZEND_HASH_FOREACH_VAL(ht, arg) { + have_named_params = 0; + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { + if (name) { + void *cache_slot[2] = {NULL, NULL}; + have_named_params = 1; + param = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot); + if (!param) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } else if (have_named_params) { + zend_throw_error(NULL, + "Cannot use positional argument after named argument"); + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + zend_bool must_wrap = 0; if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { if (UNEXPECTED(!Z_ISREF_P(arg))) { @@ -2128,24 +2422,63 @@ send_array: arg = Z_REFVAL_P(arg); } } + if (EXPECTED(!must_wrap)) { ZVAL_COPY(param, arg); } else { Z_TRY_ADDREF_P(arg); ZVAL_NEW_REF(param, arg); } - ZEND_CALL_NUM_ARGS(EX(call))++; - arg_num++; - param++; + if (!name) { + ZEND_CALL_NUM_ARGS(EX(call))++; + arg_num++; + param++; + } } ZEND_HASH_FOREACH_END(); } } - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_missing_arg_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +{ +#ifdef ZEND_VM_IP_GLOBAL_REG + USE_OPLINE + + SAVE_OPLINE(); +#endif + zend_missing_arg_error(execute_data); + HANDLE_EXCEPTION(); +} + +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_verify_recv_arg_type_helper_SPEC(zval *op_1 ZEND_OPCODE_HANDLER_ARGS_DC) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value)))) { + HANDLE_EXCEPTION(); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_NOTYPE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num = opline->op1.num; + + if (UNEXPECTED(arg_num > EX_NUM_ARGS())) { + ZEND_VM_TAIL_CALL(zend_missing_arg_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + ZEND_VM_NEXT_OPCODE(); +} + static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC) { + int ret; USE_OPLINE SAVE_OPLINE(); @@ -2155,32 +2488,20 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_ if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { op_2 = ZVAL_UNDEFINED_OP2(); } - compare_function(EX_VAR(opline->result.var), op_1, op_2); + ret = zend_compare(op_1, op_2); if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op_2); } - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) { - ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + ZEND_VM_SMART_BRANCH(ret == 0, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; SAVE_OPLINE(); - op1 = get_zval_ptr(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + op1 = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); add_unpack_again: if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) { @@ -2191,7 +2512,7 @@ add_unpack_again: ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { if (key) { zend_throw_error(NULL, "Cannot unpack array with string keys"); - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); HANDLE_EXCEPTION(); } else { if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) { @@ -2210,11 +2531,11 @@ add_unpack_again: zend_object_iterator *iter; if (!ce || !ce->get_iterator) { - zend_throw_error(NULL, "Only arrays and Traversables can be unpacked"); + zend_type_error("Only arrays and Traversables can be unpacked"); } else { iter = ce->get_iterator(ce, op1, 0); if (UNEXPECTED(!iter)) { - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); if (!EG(exception)) { zend_throw_exception_ex( NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name) @@ -2276,7 +2597,7 @@ add_unpack_again: zend_throw_error(NULL, "Only arrays and Traversables can be unpacked"); } - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2286,7 +2607,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP zval *varname; zend_string *name, *tmp_name = NULL; zend_class_entry *ce; - zend_free_op free_op1; SAVE_OPLINE(); @@ -2295,8 +2615,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - FREE_UNFETCHED_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op1_type, opline->op1.var); HANDLE_EXCEPTION(); } /*CACHE_PTR(opline->extended_value, ce);*/ @@ -2304,15 +2623,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP } else if (opline->op2_type == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - FREE_UNFETCHED_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op1_type, opline->op1.var); HANDLE_EXCEPTION(); } } else { ce = Z_CE_P(EX_VAR(opline->op2.var)); } - varname = get_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + varname = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); if (opline->op1_type == IS_CONST) { name = Z_STR_P(varname); } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { @@ -2321,13 +2639,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { varname = ZVAL_UNDEFINED_OP1(); } - name = zval_get_tmp_string(varname, &tmp_name); + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } } zend_std_unset_static_property(ce, name); zend_tmp_string_release(tmp_name); - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2335,22 +2657,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC { USE_OPLINE zval *value; - int result; + zend_result fetch_result; + bool result; SAVE_OPLINE(); - result = zend_fetch_static_property_address(&value, NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC); + fetch_result = zend_fetch_static_property_address(&value, NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC); if (!(opline->extended_value & ZEND_ISEMPTY)) { - result = result == SUCCESS && Z_TYPE_P(value) > IS_NULL && + result = fetch_result == SUCCESS && Z_TYPE_P(value) > IS_NULL && (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); } else { - result = result != SUCCESS || !i_zend_is_true(value); + result = fetch_result != SUCCESS || !i_zend_is_true(value); } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -2359,8 +2680,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_HANDLER SAVE_OPLINE(); if (opline->op1_type != IS_UNUSED) { - zend_free_op free_op1; - zval *ptr = get_zval_ptr(opline->op1_type, opline->op1, &free_op1, BP_VAR_R); + zval *ptr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); do { if (Z_TYPE_P(ptr) == IS_LONG) { @@ -2376,10 +2696,13 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_HANDLER zend_print_zval(ptr, 0); } } while (0); - FREE_OP(free_op1); + FREE_OP(opline->op1_type, opline->op1.var); } - zend_bailout(); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ + + if (!EG(exception)) { + zend_throw_unwind_exit(); + } + HANDLE_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -2388,9 +2711,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EG(error_reporting)) { + if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) { do { - EG(error_reporting) = 0; + /* Do not silence fatal errors */ + EG(error_reporting) &= E_FATAL_ERRORS; if (!EG(error_reporting_ini_entry)) { zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1); if (zv) { @@ -2533,7 +2857,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try zend_object *ex = EG(exception); /* Walk try/catch/finally structures upwards, performing the necessary actions */ - while (try_catch_offset != (uint32_t) -1) { + for (; try_catch_offset != (uint32_t) -1; try_catch_offset--) { zend_try_catch_element *try_catch = &EX(func)->op_array.try_catch_array[try_catch_offset]; @@ -2543,6 +2867,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0); } else if (op_num < try_catch->finally_op) { + if (ex && zend_is_unwind_exit(ex)) { + /* Don't execute finally blocks on exit (for now) */ + continue; + } + /* Go to finally block */ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var); cleanup_live_vars(execute_data, op_num, try_catch->finally_op); @@ -2572,11 +2901,12 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try ex = Z_OBJ_P(fast_call); } } - - try_catch_offset--; } /* Uncaught exception */ + if (zend_observer_fcall_op_array_extension != -1) { + zend_observer_fcall_end(execute_data, NULL); + } cleanup_live_vars(execute_data, op_num, 0); if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); @@ -2635,7 +2965,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( break; /* return value is zend_class_entry pointer */ default: - zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var)); + /* smart branch opcodes may not initialize result */ + if (!zend_is_smart_branch(throw_op)) { + zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var)); + } } } @@ -2679,8 +3012,8 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_yi SAVE_OPLINE(); zend_throw_error(NULL, "Cannot yield from finally in a force-closed generator"); - FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); - FREE_UNFETCHED_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -2760,7 +3093,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z zend_array *args = NULL; zend_function *fbc = EX(func); zval *ret = EX(return_value); - uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS); + uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS); uint32_t num_args = EX_NUM_ARGS(); zend_execute_data *call; @@ -2788,10 +3121,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); + + zval *call_args = ZEND_CALL_ARG(call, 2); if (args) { - ZVAL_ARR(ZEND_CALL_ARG(call, 2), args); + ZVAL_ARR(call_args, args); } else { - ZVAL_EMPTY_ARRAY(ZEND_CALL_ARG(call, 2)); + ZVAL_EMPTY_ARRAY(call_args); + } + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + if (zend_hash_num_elements(Z_ARRVAL_P(call_args)) == 0) { + GC_ADDREF(call->extra_named_params); + ZVAL_ARR(call_args, call->extra_named_params); + } else { + SEPARATE_ARRAY(call_args); + zend_hash_copy(Z_ARRVAL_P(call_args), call->extra_named_params, zval_add_ref); + } } zend_free_trampoline(fbc); fbc = call->func; @@ -2804,9 +3148,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } else { SAVE_OPLINE_EX(); + execute_data = EX(prev_execute_data); LOAD_OPLINE(); ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); @@ -2819,14 +3166,145 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z EG(current_execute_data) = call; - if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) - && UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) { - zend_vm_stack_free_call_frame(call); - if (ret) { - ZVAL_UNDEF(ret); +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + + if (ret == NULL) { + ret = &retval; + } + + ZVAL_NULL(ret); + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(call, ret); + } else { + zend_execute_internal(call, ret); + } + +#if ZEND_DEBUG + if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); } - goto call_trampoline_end; + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } +#endif + + EG(current_execute_data) = call->prev_execute_data; + + zend_vm_stack_free_args(call); + if (ret == &retval) { + zval_ptr_dtor(ret); + } + } + + execute_data = EG(current_execute_data); + + if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { + ZEND_VM_RETURN(); + } + + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + zend_object *object = Z_OBJ(call->This); + OBJ_RELEASE(object); + } + zend_vm_stack_free_call_frame(call); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION_LEAVE(); + } + + LOAD_OPLINE(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_array *args = NULL; + zend_function *fbc = EX(func); + zval *ret = EX(return_value); + uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS); + uint32_t num_args = EX_NUM_ARGS(); + zend_execute_data *call; + + SAVE_OPLINE(); + + if (num_args) { + zval *p = ZEND_CALL_ARG(execute_data, 1); + zval *end = p + num_args; + + args = zend_new_array(num_args); + zend_hash_real_init_packed(args); + ZEND_HASH_FILL_PACKED(args) { + do { + ZEND_HASH_FILL_ADD(p); + p++; + } while (p != end); + } ZEND_HASH_FILL_END(); + } + + call = execute_data; + execute_data = EG(current_execute_data) = EX(prev_execute_data); + + call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call; + ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + ZEND_CALL_NUM_ARGS(call) = 2; + + ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); + + zval *call_args = ZEND_CALL_ARG(call, 2); + if (args) { + ZVAL_ARR(call_args, args); + } else { + ZVAL_EMPTY_ARRAY(call_args); + } + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + if (zend_hash_num_elements(Z_ARRVAL_P(call_args)) == 0) { + GC_ADDREF(call->extra_named_params); + ZVAL_ARR(call_args, call->extra_named_params); + } else { + SEPARATE_ARRAY(call_args); + zend_hash_copy(Z_ARRVAL_P(call_args), call->extra_named_params, zval_add_ref); + } + } + zend_free_trampoline(fbc); + fbc = call->func; + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + if (UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); } + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + if (EXPECTED(zend_execute_ex == execute_ex)) { + LOAD_OPLINE_EX(); + SAVE_OPLINE(); + zend_observer_fcall_begin(execute_data); + ZEND_VM_ENTER_EX(); + } else { + SAVE_OPLINE_EX(); + zend_observer_fcall_begin(execute_data); + execute_data = EX(prev_execute_data); + LOAD_OPLINE(); + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + } + } else { + zval retval; + + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + + EG(current_execute_data) = call; + +#if ZEND_DEBUG + zend_bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif if (ret == NULL) { ret = &retval; @@ -2842,6 +3320,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z #if ZEND_DEBUG if (!EG(exception) && call->func) { + if (should_throw) { + zend_internal_call_arginfo_violation(call->func); + } ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) @@ -2851,7 +3332,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z EG(current_execute_data) = call->prev_execute_data; -call_trampoline_end: zend_vm_stack_free_args(call); if (ret == &retval) { zval_ptr_dtor(ret); @@ -2893,7 +3373,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_he EG(vm_interrupt) = 0; SAVE_OPLINE(); if (EG(timed_out)) { - zend_timeout(0); + zend_timeout(); } else if (zend_interrupt_function) { zend_interrupt_function(execute_data); ZEND_VM_ENTER(); @@ -2931,7 +3411,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_execute_data *call; @@ -2942,7 +3421,7 @@ try_function_name: if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -2950,20 +3429,18 @@ try_function_name: goto try_function_name; } else { if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + function_name = ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Value of type %s is not callable", + zend_zval_type_name(function_name)); call = NULL; } - if (UNEXPECTED(!call)) { - HANDLE_EXCEPTION(); - } - if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { + if (UNEXPECTED(EG(exception))) { if (call) { if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { @@ -2974,6 +3451,8 @@ try_function_name: } HANDLE_EXCEPTION(); } + } else if (!call) { + HANDLE_EXCEPTION(); } call->prev_execute_data = EX(call); @@ -3084,10 +3563,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON } else { recv_init_check_type: if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - zval *default_value = RT_CONSTANT(opline, opline->op2); - SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } @@ -3100,18 +3577,17 @@ recv_init_check_type: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *function_name; zend_execute_data *call; SAVE_OPLINE(); - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); try_function_name: if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3119,21 +3595,18 @@ try_function_name: goto try_function_name; } else { if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + function_name = ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Value of type %s is not callable", + zend_zval_type_name(function_name)); call = NULL; } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(!call)) { - HANDLE_EXCEPTION(); - } - if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (UNEXPECTED(EG(exception))) { if (call) { if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { @@ -3144,6 +3617,8 @@ try_function_name: } HANDLE_EXCEPTION(); } + } else if (!call) { + HANDLE_EXCEPTION(); } call->prev_execute_data = EX(call); @@ -3156,18 +3631,16 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_H { USE_OPLINE uint32_t arg_num = opline->op1.num; + zval *param; if (UNEXPECTED(arg_num > EX_NUM_ARGS())) { - SAVE_OPLINE(); - zend_missing_arg_error(execute_data); - HANDLE_EXCEPTION(); - } else { - zval *param = EX_VAR(opline->result.var); + ZEND_VM_TAIL_CALL(zend_missing_arg_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } - SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) { - HANDLE_EXCEPTION(); - } + param = EX_VAR(opline->result.var); + + if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param))))) { + ZEND_VM_TAIL_CALL(zend_verify_recv_arg_type_helper_SPEC(param ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } ZEND_VM_NEXT_OPCODE(); @@ -3185,16 +3658,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND params = EX_VAR(opline->result.var); if (arg_num <= arg_count) { - zval *param; + ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_VARIADIC); + ZEND_ASSERT(EX(func)->common.num_args == arg_num - 1); + zend_arg_info *arg_info = &EX(func)->common.arg_info[arg_num - 1]; array_init_size(params, arg_count - arg_num + 1); zend_hash_real_init_packed(Z_ARRVAL_P(params)); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) { - param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); - if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { + zval *param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); + if (UNEXPECTED(ZEND_TYPE_IS_SET(arg_info->type))) { ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS); do { - zend_verify_variadic_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)); + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { + ZEND_HASH_FILL_FINISH(); + HANDLE_EXCEPTION(); + } + if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); ZEND_HASH_FILL_ADD(param); param++; @@ -3211,13 +3690,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND ZVAL_EMPTY_ARRAY(params); } + if (EX_CALL_INFO() & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_string *name; + zval *param; + zend_arg_info *arg_info = &EX(func)->common.arg_info[EX(func)->common.num_args]; + if (ZEND_TYPE_IS_SET(arg_info->type)) { + SEPARATE_ARRAY(params); + ZEND_HASH_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { + HANDLE_EXCEPTION(); + } + Z_TRY_ADDREF_P(param); + zend_hash_add_new(Z_ARRVAL_P(params), name, param); + } ZEND_HASH_FOREACH_END(); + } else if (zend_hash_num_elements(Z_ARRVAL_P(params)) == 0) { + GC_ADDREF(EX(extra_named_params)); + ZVAL_ARR(params, EX(extra_named_params)); + } else { + SEPARATE_ARRAY(params); + ZEND_HASH_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { + Z_TRY_ADDREF_P(param); + zend_hash_add_new(Z_ARRVAL_P(params), name, param); + } ZEND_HASH_FOREACH_END(); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_execute_data *call; @@ -3228,7 +3731,7 @@ try_function_name: if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3236,20 +3739,18 @@ try_function_name: goto try_function_name; } else { if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + function_name = ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Value of type %s is not callable", + zend_zval_type_name(function_name)); call = NULL; } - if (UNEXPECTED(!call)) { - HANDLE_EXCEPTION(); - } - if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (UNEXPECTED(EG(exception))) { if (call) { if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { @@ -3260,6 +3761,8 @@ try_function_name: } HANDLE_EXCEPTION(); } + } else if (!call) { + HANDLE_EXCEPTION(); } call->prev_execute_data = EX(call); @@ -3271,7 +3774,6 @@ try_function_name: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; op1 = RT_CONSTANT(opline, opline->op1); @@ -3280,13 +3782,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_CONST ZEND_VM_NEXT_OPCODE(); } - SAVE_OPLINE(); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - op1 = ZVAL_UNDEFINED_OP1(); - } - bitwise_not_function(EX_VAR(opline->result.var), op1); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_TAIL_CALL(zend_bw_not_helper_SPEC(op1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -3294,7 +3790,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CON USE_OPLINE zval *val; - val = RT_CONSTANT(opline, opline->op1); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -3319,7 +3814,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *z; SAVE_OPLINE(); @@ -3348,8 +3842,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_O static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = RT_CONSTANT(opline, opline->op1); @@ -3367,20 +3861,23 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_H } SAVE_OPLINE(); + op1_type = IS_CONST; if (i_zend_is_true(val)) { opline++; } else { opline = OP_JMP_ADDR(opline, opline->op2); } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = RT_CONSTANT(opline, opline->op1); @@ -3398,20 +3895,23 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_ } SAVE_OPLINE(); + op1_type = IS_CONST; if (i_zend_is_true(val)) { opline = OP_JMP_ADDR(opline, opline->op2); } else { opline++; } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = RT_CONSTANT(opline, opline->op1); @@ -3430,21 +3930,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CONST_HANDLER(ZEND } SAVE_OPLINE(); + op1_type = IS_CONST; if (i_zend_is_true(val)) { opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); } else { opline = OP_JMP_ADDR(opline, opline->op2); } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; - int ret; + bool ret; val = RT_CONSTANT(opline, opline->op1); @@ -3479,9 +3981,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONS static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; - int ret; + bool ret; val = RT_CONSTANT(opline, opline->op1); @@ -3517,10 +4018,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = RT_CONSTANT(opline, opline->op1); return_value = EX(return_value); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -3529,9 +4030,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ } } else if (!return_value) { if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -3546,7 +4047,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { @@ -3582,16 +4083,98 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ } } } + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; + zval *return_value; + zval observer_retval; + retval_ptr = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); + return_value = EX(return_value); + if (!return_value) { return_value = &observer_retval; }; + if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); + } + } + } else { + if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (opline->op1_type == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (opline->op1_type == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (opline->op1_type == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } + } + } SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, return_value); + if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + SAVE_OPLINE(); + + return_value = EX(return_value); do { if ((IS_CONST & (IS_CONST|IS_TMP_VAR)) || @@ -3600,15 +4183,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE zend_error(E_NOTICE, "Only variable references should be returned by reference"); retval_ptr = RT_CONSTANT(opline, opline->op1); - if (!EX(return_value)) { + if (!return_value) { } else { if (IS_CONST == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (IS_CONST == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } @@ -3622,8 +4205,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { } @@ -3631,17 +4214,84 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } } while (0); + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + zval observer_retval; + + SAVE_OPLINE(); + + return_value = EX(return_value); + if (!return_value) { return_value = &observer_retval; }; + do { + if ((opline->op1_type & (IS_CONST|IS_TMP_VAR)) || + (opline->op1_type == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + + retval_ptr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + if (!return_value) { + FREE_OP(opline->op1_type, opline->op1.var); + } else { + if (opline->op1_type == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + break; + } + + ZVAL_NEW_REF(return_value, retval_ptr); + if (opline->op1_type == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } + } + break; + } + + retval_ptr = get_zval_ptr_ptr(opline->op1_type, opline->op1, BP_VAR_W); + + if (opline->op1_type == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); + } else { + if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}; + } + break; + } + } + + if (return_value) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); + } + + if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}; + } while (0); + + zend_observer_fcall_end(execute_data, return_value); + if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -3650,7 +4300,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CONST_HA USE_OPLINE zval *retval; - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); @@ -3689,12 +4338,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CONST_HA ZEND_VM_RETURN(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + retval = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + + /* Copy return value into generator->retval */ + if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (opline->op1_type == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (opline->op1_type == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (opline->op1_type == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); + + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } + + zend_observer_fcall_end(generator->execute_data, &generator->retval); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; - SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op1); @@ -3719,10 +4412,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_ } while (0); zend_exception_save(); - if (IS_CONST != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - + Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); zend_exception_restore(); @@ -3734,7 +4424,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_HANDLER(ZEND_ USE_OPLINE zend_class_entry *ce, *catch_ce; zend_object *exception; - zval *ex; SAVE_OPLINE(); /* Check whether an exception has been thrown, if not, jump over code */ @@ -3767,86 +4456,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_HANDLER(ZEND_ } exception = EG(exception); - ex = EX_VAR(opline->result.var); - { + EG(exception) = NULL; + if (RETURN_VALUE_USED(opline)) { /* Always perform a strict assignment. There is a reasonable expectation that if you * write "catch (Exception $e)" then $e will actually be instanceof Exception. As such, * we should not permit coercion to string here. */ zval tmp; ZVAL_OBJ(&tmp, exception); - EG(exception) = NULL; - zend_assign_to_variable(ex, &tmp, IS_TMP_VAR, /* strict */ 1); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - - - value = RT_CONSTANT(opline, opline->op1); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, value); - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); - } - } - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(0)) { - if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_val_by_ref; - } - } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - value = RT_CONSTANT(opline, opline->op1); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, value); - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); - } - } - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(1)) { - if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_val_by_ref; - } - } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - value = RT_CONSTANT(opline, opline->op1); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, value); - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); - } + zend_assign_to_variable(EX_VAR(opline->result.var), &tmp, IS_TMP_VAR, /* strict */ 1); + } else { + OBJ_RELEASE(exception); } - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -3854,7 +4475,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CONST_HANDLER(Z USE_OPLINE zval *arg, *param; - SAVE_OPLINE(); if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { @@ -3873,7 +4493,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_H USE_OPLINE zval *val; - val = RT_CONSTANT(opline, opline->op1); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); @@ -3898,8 +4517,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_H static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -3907,10 +4526,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ SAVE_OPLINE(); obj = RT_CONSTANT(opline, opline->op1); - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - do { if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { @@ -3933,9 +4548,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -3956,7 +4572,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -3964,7 +4580,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; @@ -3973,12 +4588,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H expr = RT_CONSTANT(opline, opline->op1); switch (opline->extended_value) { - case IS_NULL: - ZVAL_NULL(result); - break; - case _IS_BOOL: - ZVAL_BOOL(result, zend_is_true(expr)); - break; case IS_LONG: ZVAL_LONG(result, zval_get_long(expr)); break; @@ -3989,6 +4598,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H ZVAL_STR(result, zval_get_string(expr)); break; default: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); if (IS_CONST & (IS_VAR|IS_CV)) { ZVAL_DEREF(expr); } @@ -4031,6 +4641,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H } } } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); if (Z_TYPE_P(expr) == IS_ARRAY) { ht = zend_symtable_to_proptable(Z_ARR_P(expr)); @@ -4058,14 +4669,82 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN { USE_OPLINE zend_op_array *new_op_array; - zval *inc_filename; SAVE_OPLINE(); inc_filename = RT_CONSTANT(opline, opline->op1); new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); + if (UNEXPECTED(EG(exception) != NULL)) { + + if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (new_op_array == ZEND_FAKE_OP_ARRAY) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + } else if (EXPECTED(new_op_array != NULL)) { + zval *return_value = NULL; + zend_execute_data *call; + + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + } + + new_op_array->scope = EX(func)->op_array.scope; + + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + (zend_function*)new_op_array, 0, + Z_PTR(EX(This))); + + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(); + } + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value); + + if (EXPECTED(zend_execute_ex == execute_ex)) { + + ZEND_VM_ENTER(); + } else { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + zend_vm_stack_free_call_frame(call); + } + + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } else if (RETURN_VALUE_USED(opline)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_op_array *new_op_array; + zval *inc_filename; + + SAVE_OPLINE(); + inc_filename = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); if (UNEXPECTED(EG(exception) != NULL)) { + FREE_OP(opline->op1_type, opline->op1.var); if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { destroy_op_array(new_op_array); efree_size(new_op_array, sizeof(zend_op_array)); @@ -4099,7 +4778,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN call->prev_execute_data = execute_data; i_init_code_execute_data(call, new_op_array, return_value); + zend_observer_fcall_begin(call); if (EXPECTED(zend_execute_ex == execute_ex)) { + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_ENTER(); } else { ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); @@ -4111,19 +4792,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN efree_size(new_op_array, sizeof(zend_op_array)); if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); + FREE_OP(opline->op1_type, opline->op1.var); UNDEF_RESULT(); HANDLE_EXCEPTION(); } } else if (RETURN_VALUE_USED(opline)) { ZVAL_FALSE(EX_VAR(opline->result.var)); } + FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *result; SAVE_OPLINE(); @@ -4139,17 +4821,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (IS_CONST != IS_TMP_VAR) { @@ -4177,7 +4862,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; @@ -4188,7 +4873,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref; SAVE_OPLINE(); @@ -4275,7 +4959,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_ } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_CONST == IS_VAR) { @@ -4290,10 +4974,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *ref = NULL; - int ret; + bool ret; SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op1); @@ -4339,7 +5022,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONS static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *ref = NULL; @@ -4375,10 +5057,44 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CON ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *val; + + val = RT_CONSTANT(opline, opline->op1); + if (IS_CONST != IS_CONST) { + ZVAL_DEREF(val); + } + + if (Z_TYPE_INFO_P(val) > IS_NULL) { + ZEND_VM_NEXT_OPCODE(); + } else { + zval *result = EX_VAR(opline->result.var); + + if (EXPECTED(opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { + ZVAL_NULL(result); + if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + } else if (opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) { + ZVAL_FALSE(result); + } else { + ZEND_ASSERT(opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY); + ZVAL_TRUE(result); + } + + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } +} +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE zval *value; zval *result = EX_VAR(opline->result.var); @@ -4426,12 +5142,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_CONST_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - zval *val; - SAVE_OPLINE(); val = RT_CONSTANT(opline, opline->op1); @@ -4442,9 +5155,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( HANDLE_EXCEPTION(); } +yield_from_try_again: if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); - if (IS_CONST != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { + if (Z_OPT_REFCOUNTED_P(val)) { Z_ADDREF_P(val); } Z_FE_POS(generator->values) = 0; @@ -4454,11 +5168,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( if (ce == zend_ce_generator) { zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - if (IS_CONST != IS_TMP_VAR) { - Z_ADDREF_P(val); - } + Z_ADDREF_P(val); - if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); zval_ptr_dtor(val); @@ -4467,11 +5184,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( } else { zend_generator_yield_from(generator, new_gen); } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); } else { if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); @@ -4501,6 +5213,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( ZVAL_OBJ(&generator->values, &iter->std); } + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; } else { zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); @@ -4533,7 +5248,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST USE_OPLINE zval *value; - value = RT_CONSTANT(opline, opline->op1); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); @@ -4570,9 +5284,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST zval_ptr_dtor(&tmp); } if (!EG(exception)) { - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + zend_type_error("strlen(): Argument #1 ($str) must be of type string, %s given", zend_zval_type_name(value)); } - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } @@ -4585,11 +5299,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_C zval *value; int result = 0; - value = RT_CONSTANT(opline, opline->op1); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -4611,12 +5324,8 @@ type_check_resource: SAVE_OPLINE(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } @@ -4630,13 +5339,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST if (!IS_SPECIAL_CACHE_VAL(c)) { defined_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) { defined_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1) OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { @@ -4650,7 +5355,6 @@ defined_false: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = RT_CONSTANT(opline, opline->op1); @@ -4661,7 +5365,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = RT_CONSTANT(opline, opline->op1); @@ -4672,7 +5375,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_S static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = RT_CONSTANT(opline, opline->op1); @@ -4685,7 +5387,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SIMPLE_SP USE_OPLINE zval *value, *arg; - value = RT_CONSTANT(opline, opline->op1); arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, value); @@ -4696,14 +5397,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SIMPLE { USE_OPLINE zval *value, *arg; - uint32_t arg_num = opline->op2.num; + arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } value = RT_CONSTANT(opline, opline->op1); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY_VALUE(arg, value); ZEND_VM_NEXT_OPCODE(); } @@ -4711,7 +5411,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SIMPLE static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -4750,7 +5449,6 @@ add_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -4789,7 +5487,6 @@ sub_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -4831,7 +5528,6 @@ mul_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -4846,7 +5542,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; op1 = RT_CONSTANT(opline, opline->op1); @@ -4874,7 +5569,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -4896,7 +5590,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CON static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -4916,7 +5609,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CON static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -4931,7 +5623,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -4942,14 +5633,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -4960,14 +5648,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -4980,13 +5665,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CON if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -5010,7 +5691,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -5030,7 +5711,6 @@ is_equal_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -5043,13 +5723,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -5073,7 +5749,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -5093,7 +5769,6 @@ is_not_equal_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -5106,13 +5781,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_C if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -5141,7 +5812,6 @@ is_smaller_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -5189,7 +5859,6 @@ is_smaller_or_equal_double: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -5204,7 +5873,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -5223,7 +5891,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -5242,7 +5909,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -5261,7 +5927,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -5276,7 +5941,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CON static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; SAVE_OPLINE(); @@ -5312,7 +5976,6 @@ fetch_dim_r_slow: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -5345,19 +6008,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_AR static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST || @@ -5375,7 +6031,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -5384,9 +6040,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -5411,10 +6069,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -5425,7 +6083,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -5437,11 +6095,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -5460,19 +6129,12 @@ fetch_obj_r_finish: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST || @@ -5492,9 +6154,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -5519,10 +6183,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -5533,7 +6197,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -5545,9 +6209,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -5583,7 +6257,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -5596,7 +6269,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -5718,7 +6390,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -5730,10 +6401,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ object = RT_CONSTANT(opline, opline->op1); - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CONST != IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); } @@ -5760,12 +6427,26 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } while (0); } - if (IS_CONST != IS_UNUSED) { + if (IS_CONST == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CONST & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -5789,7 +6470,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if (IS_CONST == IS_CONST && @@ -5809,18 +6489,21 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -5833,9 +6516,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -5843,9 +6528,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -5876,7 +6558,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -5887,7 +6568,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } else if (IS_CONST == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -5904,8 +6584,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { - - function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -5921,7 +6599,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -5941,7 +6619,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -5972,13 +6649,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -6003,7 +6676,6 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; @@ -6015,16 +6687,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS SAVE_OPLINE(); function_name = RT_CONSTANT(opline, opline->op2); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -6056,14 +6720,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s(): Argument #1 ($function) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -6074,6 +6734,71 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS ZEND_VM_NEXT_OPCODE(); } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry *ce, *scope; @@ -6093,7 +6818,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS } else { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -6102,7 +6826,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS if (IS_CONST == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -6120,7 +6843,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS c = Z_PTR_P(zv); scope = EX(func)->op_array.scope; if (!zend_verify_const_access(c, scope)) { - zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -6134,7 +6857,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS } CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); } else { - zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -6148,7 +6872,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -6187,7 +6910,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C } if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); zend_string *str; zend_ulong hval; @@ -6267,9 +6989,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HA static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; + bool result; zend_ulong hval; zval *offset; @@ -6317,8 +7038,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -6344,25 +7063,18 @@ isset_dim_obj_exit: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST || @@ -6379,26 +7091,37 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -6416,13 +7139,12 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -6459,7 +7181,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *name; zval *val; zend_constant c; @@ -6507,8 +7228,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER /* Set the new yielded value */ if (IS_CONST != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -6576,26 +7295,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -6631,12 +7335,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op, *jump_zv; HashTable *jumptable; op = RT_CONSTANT(opline, opline->op1); - jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); if (Z_TYPE_P(op) != IS_LONG) { ZVAL_DEREF(op); @@ -6646,6 +7348,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_ } } + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op)); if (jump_zv != NULL) { ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); @@ -6660,12 +7363,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op, *jump_zv; HashTable *jumptable; op = RT_CONSTANT(opline, opline->op1); - jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); if (Z_TYPE_P(op) != IS_STRING) { if (IS_CONST == IS_CONST) { @@ -6680,6 +7381,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPE } } + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), IS_CONST == IS_CONST); if (jump_zv != NULL) { ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); @@ -6691,10 +7393,50 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPE } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *op, *jump_zv; + HashTable *jumptable; + + op = RT_CONSTANT(opline, opline->op1); + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + +match_try_again: + if (Z_TYPE_P(op) == IS_LONG) { + jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op)); + } else if (Z_TYPE_P(op) == IS_STRING) { + jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), IS_CONST == IS_CONST); + } else if (Z_TYPE_P(op) == IS_REFERENCE) { + op = Z_REFVAL_P(op); + goto match_try_again; + } else { + if (UNEXPECTED((IS_CONST & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) { + SAVE_OPLINE(); + op = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + goto match_try_again; + } + + goto default_branch; + } + if (jump_zv != NULL) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); + ZEND_VM_CONTINUE(); + } else { +default_branch: + /* default */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; @@ -6713,13 +7455,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } @@ -6727,14 +7468,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -6773,7 +7511,6 @@ add_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -6812,7 +7549,6 @@ sub_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; op1 = RT_CONSTANT(opline, opline->op1); @@ -6840,7 +7576,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -6862,7 +7597,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -6882,7 +7616,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -6894,14 +7627,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_smaller_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -6930,7 +7659,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -6943,13 +7671,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CO if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -6978,7 +7702,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -6991,13 +7714,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CO if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -7026,7 +7745,6 @@ is_smaller_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -7038,12 +7756,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { is_smaller_or_equal_true: - + ZEND_VM_SMART_BRANCH_TRUE_NONE(); ZVAL_TRUE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } else { is_smaller_or_equal_false: - + ZEND_VM_SMART_BRANCH_FALSE_NONE(); ZVAL_FALSE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -7074,7 +7792,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -7122,7 +7839,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -7207,174 +7923,149 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMP { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = RT_CONSTANT(opline, opline->op1); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; zend_long offset; HashTable *ht; @@ -7427,41 +8118,38 @@ fetch_dim_r_index_undef: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -7521,7 +8209,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -7529,27 +8217,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container, *dim, *value; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: @@ -7572,7 +8258,7 @@ fetch_dim_r_slow: } else { zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7580,13 +8266,12 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7613,20 +8298,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -7643,7 +8321,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -7652,9 +8330,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -7679,10 +8359,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -7693,7 +8373,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -7705,11 +8385,22 @@ fetch_obj_r_fast_copy: } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -7720,7 +8411,7 @@ fetch_obj_r_copy: } while (0); fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7728,20 +8419,13 @@ fetch_obj_r_finish: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -7760,9 +8444,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -7787,10 +8473,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -7801,7 +8487,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -7813,9 +8499,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -7826,7 +8522,7 @@ fetch_obj_is_copy: } while (0); fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7851,26 +8547,24 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; op1 = RT_CONSTANT(opline, opline->op1); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); @@ -7978,7 +8672,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7986,7 +8680,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -7998,12 +8691,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ object = RT_CONSTANT(opline, opline->op1); - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST && @@ -8022,18 +8711,32 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } - if (IS_CONST != IS_UNUSED) { + if (IS_CONST == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CONST & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -8041,23 +8744,22 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if ((IS_TMP_VAR|IS_VAR) == IS_CONST && @@ -8067,7 +8769,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ @@ -8076,19 +8778,22 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); - + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -8096,14 +8801,16 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -8111,9 +8818,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -8144,7 +8848,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -8155,7 +8858,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } else if (IS_CONST == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -8172,9 +8874,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { @@ -8189,8 +8889,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } @@ -8205,11 +8905,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (EXPECTED(!EG(exception))) { zend_undefined_method(ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -8217,7 +8916,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C init_func_run_time_cache(&fbc->op_array); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -8240,13 +8939,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -8271,7 +8966,6 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; @@ -8281,18 +8975,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; SAVE_OPLINE(); - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -8311,7 +8997,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { if (call_info & ZEND_CALL_CLOSURE) { zend_object_release(ZEND_CLOSURE_OBJECT(func)); @@ -8325,14 +9011,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s(): Argument #1 ($function) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -8346,7 +9028,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -8385,8 +9066,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; @@ -8431,7 +9111,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -8465,15 +9145,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; - int result; + bool result; zend_ulong hval; zval *offset; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -8513,10 +9192,8 @@ num_index_prop: if (IS_CONST & (IS_CONST|IS_CV)) { /* avoid exception check */ - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -8539,29 +9216,22 @@ num_index_prop: } isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -8577,31 +9247,42 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); key = RT_CONSTANT(opline, opline->op1); - subject = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { array_key_exists_array: @@ -8614,158 +9295,17 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_CONST != IS_UNUSED) { - - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = RT_CONSTANT(opline, opline->op1); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = NULL; - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_CONST == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = RT_CONSTANT(opline, opline->op1); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8784,8 +9324,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z /* Set the new yielded value */ if (IS_CONST != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -8852,27 +9390,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z } /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -8908,7 +9432,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE - zval *varname; zval *retval; zend_string *name, *tmp_name; @@ -8950,7 +9473,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -8969,7 +9492,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { ZVAL_NULL(retval); } else { @@ -9066,7 +9589,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -9077,7 +9599,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } else if (IS_CONST == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -9094,8 +9615,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { - - function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -9111,7 +9630,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -9131,7 +9650,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -9162,13 +9680,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -9192,18 +9706,16 @@ check_parent_and_self: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - SAVE_OPLINE(); if (IS_CONST == IS_UNUSED) { - zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_CONST != IS_UNUSED) + USE_OPLINE zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = RT_CONSTANT(opline, opline->op1); if (IS_CONST == IS_CONST) { @@ -9211,33 +9723,155 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP retval_ref = retval_ptr = EX_VAR(opline->result.var); } else if (IS_CONST == IS_VAR) { if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { - retval_ptr = Z_INDIRECT_P(retval_ptr); + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); } ZVAL_DEREF(retval_ptr); } else if (IS_CONST == IS_CV) { ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -9254,7 +9888,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -9263,7 +9896,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( } else if (IS_CONST == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -9314,7 +9946,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -9353,7 +9984,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U } if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -9437,7 +10067,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA zend_string *name, *tmp_name; HashTable *target_symbol_table; - SAVE_OPLINE(); varname = RT_CONSTANT(opline, opline->op1); @@ -9473,8 +10102,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U { USE_OPLINE zval *value; + /* Should be bool result? as below got: result = (opline->extended_value & ZEND_ISEMPTY) */ int result; - zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; @@ -9511,8 +10140,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ @@ -9570,8 +10197,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE /* Set the new yielded value */ if (IS_CONST != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -9639,26 +10264,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -9691,23 +10301,36 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE ZEND_VM_RETURN(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *op; + + SAVE_OPLINE(); + op = RT_CONSTANT(opline, opline->op1); + zend_throw_exception_ex(zend_ce_unhandled_match_error, 0, "Unhandled match value of type %s", zend_zval_type_name(op)); + HANDLE_EXCEPTION(); +} +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE zval *op1; zend_long count; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); + while (1) { if (Z_TYPE_P(op1) == IS_ARRAY) { count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } if (UNEXPECTED(EG(exception))) { @@ -9717,29 +10340,24 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_ } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; } - /* If There's no handler and it doesn't implement Countable then add a warning */ - count = 1; + /* If There's no handler and it doesn't implement Countable then emit a TypeError */ } else if ((IS_CONST & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { op1 = Z_REFVAL_P(op1); continue; - } else if (Z_TYPE_P(op1) <= IS_NULL) { - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - count = 0; - } else { - count = 1; + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count"); + count = 0; + zend_type_error("%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1)); break; } @@ -9755,15 +10373,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CO if (IS_CONST == IS_UNUSED) { if (UNEXPECTED(!EX(func)->common.scope)) { SAVE_OPLINE(); - zend_error(E_WARNING, "get_class() called without object from outside a class"); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } else { ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); ZEND_VM_NEXT_OPCODE(); } } else { - zval *op1; SAVE_OPLINE(); @@ -9778,8 +10395,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CO if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_type_name(op1)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } @@ -9791,13 +10408,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CO static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; zend_string *type; SAVE_OPLINE(); op1 = RT_CONSTANT(opline, opline->op1); - type = zend_zval_get_type(op1); + type = zend_zval_get_legacy_type(op1); if (EXPECTED(type)) { ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); } else { @@ -9885,7 +10501,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -9900,7 +10515,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -9915,7 +10529,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = RT_CONSTANT(opline, opline->op1); @@ -9987,7 +10600,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -10002,7 +10614,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; SAVE_OPLINE(); @@ -10038,7 +10649,6 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -10071,19 +10681,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = EX_VAR(opline->op2.var); if (IS_CONST == IS_CONST || @@ -10101,7 +10704,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -10110,9 +10713,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -10137,10 +10742,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -10151,7 +10756,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -10163,11 +10768,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -10186,19 +10802,12 @@ fetch_obj_r_finish: static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || @@ -10218,9 +10827,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -10245,10 +10856,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -10259,7 +10870,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -10271,9 +10882,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -10309,7 +10930,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -10322,7 +10942,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -10444,7 +11063,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -10456,10 +11074,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ object = RT_CONSTANT(opline, opline->op1); - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CV != IS_CONST) { function_name = EX_VAR(opline->op2.var); } @@ -10486,12 +11100,26 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } while (0); } - if (IS_CONST != IS_UNUSED) { + if (IS_CONST == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CONST & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -10515,7 +11143,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if (IS_CV == IS_CONST && @@ -10535,18 +11162,21 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -10559,9 +11189,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -10569,9 +11201,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -10602,7 +11231,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -10613,7 +11241,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } else if (IS_CONST == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -10630,8 +11257,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { - - function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -10647,7 +11272,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -10667,7 +11292,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -10698,13 +11322,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_CONST == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -10729,7 +11349,6 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; @@ -10741,16 +11360,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H SAVE_OPLINE(); function_name = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - } object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ @@ -10782,14 +11393,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s(): Argument #1 ($function) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - object_or_called_scope = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, @@ -10803,7 +11410,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -10842,7 +11448,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C } if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); zend_string *str; zend_ulong hval; @@ -10922,9 +11527,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; + bool result; zend_ulong hval; zval *offset; @@ -10972,8 +11576,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -10999,25 +11601,18 @@ isset_dim_obj_exit: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); - - if (IS_CONST == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST || @@ -11034,26 +11629,37 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -11071,13 +11677,12 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -11100,8 +11705,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE /* Set the new yielded value */ if (IS_CONST != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -11169,26 +11772,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -11221,10 +11809,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE ZEND_VM_RETURN(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *op1; + + op1 = EX_VAR(opline->op1.var); + if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), ~Z_LVAL_P(op1)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_bw_not_helper_SPEC(op1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + + val = EX_VAR(opline->op1.var); + if ((IS_TMP_VAR|IS_VAR|IS_CV) != IS_CONST) { + ZVAL_DEREF(val); + } + + if (Z_TYPE_INFO_P(val) > IS_NULL) { + ZEND_VM_NEXT_OPCODE(); + } else { + zval *result = EX_VAR(opline->result.var); + + if (EXPECTED(opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { + ZVAL_NULL(result); + if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + } else if (opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) { + ZVAL_FALSE(result); + } else { + ZEND_ASSERT(opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY); + ZVAL_TRUE(result); + } + + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE zval *value; value = EX_VAR(opline->op1.var); @@ -11235,7 +11871,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = EX_VAR(opline->op1.var); @@ -11246,7 +11881,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_S static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; value = EX_VAR(opline->op1.var); @@ -11257,7 +11891,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SP static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -11296,7 +11929,6 @@ add_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -11335,7 +11967,6 @@ sub_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -11377,7 +12008,6 @@ mul_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; op1 = EX_VAR(opline->op1.var); @@ -11405,7 +12035,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11427,7 +12056,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11447,7 +12075,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11459,14 +12086,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_smaller_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -11495,7 +12118,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11508,13 +12130,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -11543,7 +12161,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11556,13 +12173,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -11591,7 +12204,6 @@ is_smaller_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11603,12 +12215,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVA if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { is_smaller_or_equal_true: - + ZEND_VM_SMART_BRANCH_TRUE_NONE(); ZVAL_TRUE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } else { is_smaller_or_equal_false: - + ZEND_VM_SMART_BRANCH_FALSE_NONE(); ZVAL_FALSE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -11639,7 +12251,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11687,7 +12298,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -11732,10 +12342,9 @@ is_smaller_or_equal_double: ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11751,10 +12360,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_CONST_HAND ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11770,10 +12378,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_CONST_HAN ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -11792,7 +12399,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -11805,12 +12411,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op, *jump_zv; HashTable *jumptable; op = EX_VAR(opline->op1.var); - jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); if (Z_TYPE_P(op) != IS_LONG) { ZVAL_DEREF(op); @@ -11820,6 +12424,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONS } } + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op)); if (jump_zv != NULL) { ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); @@ -11834,12 +12439,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op, *jump_zv; HashTable *jumptable; op = EX_VAR(opline->op1.var); - jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); if (Z_TYPE_P(op) != IS_STRING) { if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { @@ -11854,6 +12457,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CO } } + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST); if (jump_zv != NULL) { ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); @@ -11865,6 +12469,47 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CO } } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op, *jump_zv; + HashTable *jumptable; + + op = EX_VAR(opline->op1.var); + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + +match_try_again: + if (Z_TYPE_P(op) == IS_LONG) { + jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op)); + } else if (Z_TYPE_P(op) == IS_STRING) { + jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST); + } else if (Z_TYPE_P(op) == IS_REFERENCE) { + op = Z_REFVAL_P(op); + goto match_try_again; + } else { + if (UNEXPECTED(((IS_TMP_VAR|IS_VAR|IS_CV) & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) { + SAVE_OPLINE(); + op = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + goto match_try_again; + } + + goto default_branch; + } + + if (jump_zv != NULL) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); + ZEND_VM_CONTINUE(); + } else { +default_branch: + /* default */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11979,342 +12624,293 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CO { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = RT_CONSTANT(opline, opline->op2); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -12353,7 +12949,6 @@ add_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -12392,7 +12987,6 @@ sub_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; double d1, d2; @@ -12434,7 +13028,6 @@ mul_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2, *result; op1 = EX_VAR(opline->op1.var); @@ -12462,7 +13055,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12484,7 +13076,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12504,7 +13095,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12516,14 +13106,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVA if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_smaller_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -12552,7 +13138,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12565,13 +13150,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -12600,7 +13181,6 @@ is_smaller_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12613,13 +13193,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { is_smaller_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_smaller_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -12648,7 +13224,6 @@ is_smaller_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12660,12 +13235,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVA if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { is_smaller_or_equal_true: - + ZEND_VM_SMART_BRANCH_TRUE_NONE(); ZVAL_TRUE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } else { is_smaller_or_equal_false: - + ZEND_VM_SMART_BRANCH_FALSE_NONE(); ZVAL_FALSE(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -12696,7 +13271,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12744,7 +13318,6 @@ is_smaller_or_equal_double: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -12789,10 +13362,9 @@ is_smaller_or_equal_double: ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12808,10 +13380,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_H ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12827,10 +13398,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_ ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(op1, op2 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -12960,382 +13530,322 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TM { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); - - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; - int result; + bool result; op1 = EX_VAR(opline->op1.var); op2 = EX_VAR(opline->op2.var); result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zval *container; + zval *op; SAVE_OPLINE(); - container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_LIST_r(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + op = EX_VAR(opline->op1.var); + zend_throw_exception_ex(zend_ce_unhandled_match_error, 0, "Unhandled match value of type %s", zend_zval_type_name(op)); + HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *op1; - - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - ZVAL_LONG(EX_VAR(opline->result.var), ~Z_LVAL_P(op1)); - ZEND_VM_NEXT_OPCODE(); - } + zval *container; SAVE_OPLINE(); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - op1 = ZVAL_UNDEFINED_OP1(); - } - bitwise_not_function(EX_VAR(opline->result.var), op1); - zval_ptr_dtor_nogc(free_op1); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_LIST_r(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13343,9 +13853,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z { USE_OPLINE zval *val; - zend_free_op free_op1; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { @@ -13360,7 +13869,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z } else { SAVE_OPLINE(); ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); @@ -13369,11 +13878,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + z = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_P(z) == IS_STRING) { zend_string *str = Z_STR_P(z); @@ -13392,17 +13900,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_ zend_string_release_ex(str, 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZEND_VM_NEXT_OPCODE(); @@ -13418,22 +13926,25 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_TMPVAR_H } SAVE_OPLINE(); + op1_type = (IS_TMP_VAR|IS_VAR); if (i_zend_is_true(val)) { opline++; } else { opline = OP_JMP_ADDR(opline, opline->op2); } - zval_ptr_dtor_nogc(free_op1); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); @@ -13449,22 +13960,25 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMPVAR_ } SAVE_OPLINE(); + op1_type = (IS_TMP_VAR|IS_VAR); if (i_zend_is_true(val)) { opline = OP_JMP_ADDR(opline, opline->op2); } else { opline++; } - zval_ptr_dtor_nogc(free_op1); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; + zend_uchar op1_type; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_INFO_P(val) == IS_TRUE)) { ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); @@ -13481,23 +13995,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER(ZEN } SAVE_OPLINE(); + op1_type = (IS_TMP_VAR|IS_VAR); if (i_zend_is_true(val)) { opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); } else { opline = OP_JMP_ADDR(opline, opline->op2); } - zval_ptr_dtor_nogc(free_op1); + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; - int ret; + bool ret; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); @@ -13516,7 +14032,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZE SAVE_OPLINE(); ret = i_zend_is_true(val); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (ret) { ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; @@ -13530,11 +14046,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *val; - int ret; + bool ret; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); @@ -13552,7 +14067,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(Z SAVE_OPLINE(); ret = i_zend_is_true(val); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (ret) { ZVAL_TRUE(EX_VAR(opline->result.var)); opline = OP_JMP_ADDR(opline, opline->op2); @@ -13577,39 +14092,68 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FREE_SPEC_TMPVA zval *var; USE_OPLINE - SAVE_OPLINE(); var = EX_VAR(opline->op1.var); - if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) { - zend_hash_iterator_del(Z_FE_ITER_P(var)); + if (Z_TYPE_P(var) != IS_ARRAY) { + SAVE_OPLINE(); + if (Z_FE_ITER_P(var) != (uint32_t)-1) { + zend_hash_iterator_del(Z_FE_ITER_P(var)); + } + zval_ptr_dtor_nogc(var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - zval_ptr_dtor_nogc(var); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + + /* This is freeing an array. Use an inlined version of zval_ptr_dtor_nogc. */ + /* PHP only needs to save the opline and check for an exception if the last reference to the array was garbage collected (destructors of elements in the array could throw an exception) */ + if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value, *arg; - zend_free_op free_op1; + zval *value; - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, value); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Can only throw objects"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } - } - ZEND_VM_NEXT_OPCODE(); + } while (0); + + zend_exception_save(); + Z_TRY_ADDREF_P(value); + zend_throw_exception_object(value); + zend_exception_restore(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; - zend_free_op free_op1; - val = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { @@ -13624,7 +14168,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_ } else { SAVE_OPLINE(); ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); @@ -13633,18 +14177,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + obj = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); do { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -13663,17 +14203,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND } } zend_throw_error(NULL, "__clone method called on non-object"); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -13684,16 +14225,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { zend_wrong_clone_call(clone, scope); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13701,14 +14242,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA { USE_OPLINE zend_op_array *new_op_array; - zend_free_op free_op1; zval *inc_filename; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + inc_filename = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); - zval_ptr_dtor_nogc(free_op1); if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { destroy_op_array(new_op_array); efree_size(new_op_array, sizeof(zend_op_array)); @@ -13742,7 +14282,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA call->prev_execute_data = execute_data; i_init_code_execute_data(call, new_op_array, return_value); + if (EXPECTED(zend_execute_ex == execute_ex)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_ENTER(); } else { ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); @@ -13754,25 +14296,132 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA efree_size(new_op_array, sizeof(zend_op_array)); if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); UNDEF_RESULT(); HANDLE_EXCEPTION(); } } else if (RETURN_VALUE_USED(opline)) { ZVAL_FALSE(EX_VAR(opline->result.var)); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + +yield_from_try_again: + if (Z_TYPE_P(val) == IS_ARRAY) { + ZVAL_COPY_VALUE(&generator->values, val); + if (Z_OPT_REFCOUNTED_P(val)) { + Z_ADDREF_P(val); + } + Z_FE_POS(generator->values) = 0; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(val); + if (ce == zend_ce_generator) { + zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); + + Z_ADDREF_P(val); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zend_object_iterator *iter = ce->get_iterator(ce, val, 0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (!EG(exception)) { + zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(&generator->values, &iter->std); + } + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; + } else { + zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + /* This is the default return value + * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; - zend_free_op free_op1; - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } else { zend_bool strict; @@ -13781,7 +14430,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN value = Z_REFVAL_P(value); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } } @@ -13805,12 +14454,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN zval_ptr_dtor(&tmp); } if (!EG(exception)) { - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + zend_type_error("strlen(): Argument #1 ($str) must be of type string, %s given", zend_zval_type_name(value)); } - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13819,12 +14468,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TM USE_OPLINE zval *value; int result = 0; - zend_free_op free_op1; - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -13844,28 +14492,85 @@ type_check_resource: } if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + uint32_t fetch_type; + zend_class_entry *called_scope, *scope; + USE_OPLINE + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *op = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_OBJECT) { + zend_type_error("Cannot use \"::class\" on value of type %s", zend_zval_type_name(op)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + fetch_type = opline->op1.num; + scope = EX(func)->op_array.scope; + if (UNEXPECTED(scope == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot use \"%s\" in the global scope", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name); + break; + case ZEND_FETCH_CLASS_PARENT: + if (UNEXPECTED(scope->parent == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, + "Cannot use \"parent\" when current class scope has no parent"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name); + break; + case ZEND_FETCH_CLASS_STATIC: + if (Z_TYPE(EX(This)) == IS_OBJECT) { + called_scope = Z_OBJCE(EX(This)); + } else { + called_scope = Z_CE(EX(This)); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13873,14 +14578,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13888,10 +14592,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CONST_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && @@ -13951,7 +14654,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL op2 = ZVAL_UNDEFINED_OP2(); } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -13960,11 +14663,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -13972,14 +14674,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14003,7 +14701,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -14023,11 +14721,10 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14036,13 +14733,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMP if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14066,7 +14759,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -14086,11 +14779,10 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14099,13 +14791,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMP if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14129,7 +14817,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -14149,11 +14837,10 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14161,14 +14848,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14192,7 +14875,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -14212,11 +14895,10 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14225,13 +14907,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14255,7 +14933,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -14275,11 +14953,10 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { /* pass */ @@ -14288,13 +14965,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14318,7 +14991,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -14338,14 +15011,13 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -14353,14 +15025,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); boolean_xor_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -14368,11 +15039,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim, *value; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -14397,40 +15067,32 @@ fetch_dim_r_slow: zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_read_IS(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -14448,7 +15110,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -14457,9 +15119,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -14484,10 +15148,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -14498,7 +15162,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -14510,11 +15174,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -14526,26 +15201,19 @@ fetch_obj_r_copy: fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -14565,9 +15233,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -14592,10 +15262,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -14606,7 +15276,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -14618,9 +15288,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -14632,19 +15312,18 @@ fetch_obj_is_copy: fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -14752,7 +15431,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ zend_string_release_ex(op2_str, 0); } } while (0); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -14761,7 +15440,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -14771,11 +15449,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_CONST != IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); @@ -14792,23 +15466,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -14826,13 +15514,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if (IS_CONST == IS_CONST && @@ -14852,18 +15539,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op1); + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -14876,10 +15566,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - zval_ptr_dtor_nogc(free_op1); - - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -14887,9 +15578,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -14903,27 +15591,50 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C ZEND_VM_NEXT_OPCODE(); } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { case_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { case_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -14947,7 +15658,7 @@ case_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (result) { goto case_true; @@ -14962,14 +15673,13 @@ case_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - int result; + bool result; zend_ulong hval; zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -15012,8 +15722,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -15037,27 +15745,20 @@ num_index_prop: isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -15074,30 +15775,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); - key = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); subject = RT_CONSTANT(opline, opline->op2); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { @@ -15111,25 +15823,23 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op1); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); try_instanceof: if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -15146,8 +15856,7 @@ try_instanceof: } else if (IS_CONST == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -15164,21 +15873,18 @@ try_instanceof: } result = 0; } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim, *value; zend_long offset; HashTable *ht; - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = RT_CONSTANT(opline, opline->op2); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_index_array: @@ -15192,7 +15898,7 @@ fetch_dim_r_index_array: ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_NEXT_OPCODE(); @@ -15211,7 +15917,7 @@ fetch_dim_r_index_slow: dim++; } zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -15219,19 +15925,18 @@ fetch_dim_r_index_undef: ZVAL_NULL(EX_VAR(opline->result.var)); SAVE_OPLINE(); zend_undefined_offset(offset); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim, *value; zend_long offset; HashTable *ht; - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_index_array: @@ -15245,7 +15950,7 @@ fetch_dim_r_index_array: ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_NEXT_OPCODE(); @@ -15264,7 +15969,7 @@ fetch_dim_r_index_slow: dim++; } zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -15272,48 +15977,45 @@ fetch_dim_r_index_undef: ZVAL_NULL(EX_VAR(opline->result.var)); SAVE_OPLINE(); zend_undefined_offset(offset); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -15372,8 +16074,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND op2 = ZVAL_UNDEFINED_OP2(); } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -15381,26 +16083,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15424,7 +16121,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -15444,12 +16141,11 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -15457,13 +16153,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15487,7 +16179,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -15507,12 +16199,11 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -15520,13 +16211,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15550,7 +16237,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -15570,26 +16257,21 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15613,7 +16295,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -15633,12 +16315,11 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -15646,13 +16327,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15676,7 +16353,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -15696,12 +16373,11 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -15709,13 +16385,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -15739,7 +16411,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -15759,42 +16431,39 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); boolean_xor_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *dim, *value; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: @@ -15817,42 +16486,34 @@ fetch_dim_r_slow: } else { zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -15869,7 +16530,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -15878,9 +16539,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -15905,10 +16568,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -15919,7 +16582,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -15931,11 +16594,22 @@ fetch_obj_r_fast_copy: } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -15946,28 +16620,21 @@ fetch_obj_r_copy: } while (0); fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -15986,9 +16653,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -16013,10 +16682,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -16027,7 +16696,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -16039,9 +16708,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -16052,21 +16731,20 @@ fetch_obj_is_copy: } while (0); fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); @@ -16173,8 +16851,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR zend_string_release_ex(op2_str, 0); } } while (0); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16182,7 +16860,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -16192,14 +16869,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST && @@ -16213,23 +16886,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -16237,23 +16924,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if ((IS_TMP_VAR|IS_VAR) == IS_CONST && @@ -16263,7 +16949,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ @@ -16272,19 +16958,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -16292,15 +16981,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - zval_ptr_dtor_nogc(free_op1); - - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -16308,9 +16998,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -16327,24 +17014,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { case_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { case_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -16368,8 +17050,8 @@ case_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); - zval_ptr_dtor_nogc(free_op2); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (result) { goto case_true; } else { @@ -16383,15 +17065,14 @@ case_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; - int result; + bool result; zend_ulong hval; zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -16431,10 +17112,8 @@ num_index_prop: if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { /* avoid exception check */ - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -16457,29 +17136,22 @@ num_index_prop: } isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -16495,31 +17167,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); - key = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - subject = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { array_key_exists_array: @@ -16532,26 +17215,24 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op2); - zval_ptr_dtor_nogc(free_op1); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); try_instanceof: if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -16568,8 +17249,7 @@ try_instanceof: } else if (IS_VAR == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -16586,23 +17266,20 @@ try_instanceof: } result = 0; } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE - zend_free_op free_op1; zval *varname; zval *retval; zend_string *name, *tmp_name; HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { name = Z_STR_P(varname); @@ -16615,7 +17292,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } name = zval_try_get_tmp_string(varname, &tmp_name); if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -16637,7 +17314,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -16656,7 +17333,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { ZVAL_NULL(retval); } else { @@ -16667,7 +17344,7 @@ fetch_this: } if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -16717,17 +17394,44 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HA } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; - zend_free_op free_op1; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { name = Z_STR_P(varname); @@ -16740,7 +17444,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H } name = zval_try_get_tmp_string(varname, &tmp_name); if (UNEXPECTED(!name)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } @@ -16751,7 +17455,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16760,14 +17464,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_ { USE_OPLINE zval *value; + /* Should be bool result? as below got: result = (opline->extended_value & ZEND_ISEMPTY) */ int result; - zend_free_op free_op1; zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { name = Z_STR_P(varname); } else { @@ -16780,7 +17484,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (!value) { result = (opline->extended_value & ZEND_ISEMPTY); @@ -16799,20 +17503,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_ } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); try_instanceof: if (Z_TYPE_P(expr) == IS_OBJECT) { @@ -16829,8 +17530,7 @@ try_instanceof: } else if (IS_UNUSED == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -16847,29 +17547,29 @@ try_instanceof: } result = 0; } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; zend_long count; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + while (1) { if (Z_TYPE_P(op1) == IS_ARRAY) { count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } if (UNEXPECTED(EG(exception))) { @@ -16879,34 +17579,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; } - /* If There's no handler and it doesn't implement Countable then add a warning */ - count = 1; + /* If There's no handler and it doesn't implement Countable then emit a TypeError */ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { op1 = Z_REFVAL_P(op1); continue; - } else if (Z_TYPE_P(op1) <= IS_NULL) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - count = 0; - } else { - count = 1; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count"); + count = 0; + zend_type_error("%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1)); break; } ZVAL_LONG(EX_VAR(opline->result.var), count); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16917,19 +17612,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_H if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { if (UNEXPECTED(!EX(func)->common.scope)) { SAVE_OPLINE(); - zend_error(E_WARNING, "get_class() called without object from outside a class"); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } else { ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); ZEND_VM_NEXT_OPCODE(); } } else { - zend_free_op free_op1; zval *op1; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); while (1) { if (Z_TYPE_P(op1) == IS_OBJECT) { ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name); @@ -16940,12 +17634,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_H if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_type_name(op1)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -16953,8 +17647,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); zval *result = EX_VAR(opline->result.var); ZVAL_COPY(result, value); ZEND_VM_NEXT_OPCODE(); @@ -16963,14 +17656,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16978,14 +17670,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16993,10 +17684,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = EX_VAR(opline->op2.var); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && @@ -17056,7 +17746,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( op2 = ZVAL_UNDEFINED_OP2(); } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -17065,14 +17755,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; SAVE_OPLINE(); - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -17080,11 +17769,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim, *value; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = EX_VAR(opline->op2.var); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -17109,40 +17797,32 @@ fetch_dim_r_slow: zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = EX_VAR(opline->op2.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -17160,7 +17840,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -17169,9 +17849,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -17196,10 +17878,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -17210,7 +17892,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -17222,11 +17904,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -17238,26 +17931,19 @@ fetch_obj_r_copy: fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -17277,9 +17963,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -17304,10 +17992,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -17318,7 +18006,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -17330,9 +18018,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -17344,19 +18042,18 @@ fetch_obj_is_copy: fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = EX_VAR(opline->op2.var); if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -17464,7 +18161,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN zend_string_release_ex(op2_str, 0); } } while (0); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -17473,7 +18170,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -17483,11 +18179,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C SAVE_OPLINE(); - object = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_CONST) { function_name = EX_VAR(opline->op2.var); @@ -17504,23 +18196,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); } - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -17538,13 +18244,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if (IS_CV == IS_CONST && @@ -17564,18 +18269,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op1); + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -17588,10 +18296,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - zval_ptr_dtor_nogc(free_op1); - - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -17599,9 +18308,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - zval_ptr_dtor_nogc(free_op1); } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -17618,24 +18324,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; double d1, d2; - op1 = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); op2 = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { case_true: ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { case_false: ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -17659,7 +18360,7 @@ case_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (result) { goto case_true; @@ -17674,14 +18375,13 @@ case_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; - int result; + bool result; zend_ulong hval; zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -17724,8 +18424,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -17749,27 +18447,20 @@ num_index_prop: isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -17786,30 +18477,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); - key = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); subject = EX_VAR(opline->op2.var); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { @@ -17823,13 +18525,12 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op1); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -17838,10 +18539,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -17850,9 +18551,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } } else if (!return_value) { if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -17867,7 +18568,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { @@ -17903,6 +18604,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA } } } + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -17910,26 +18614,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER { USE_OPLINE zval *retval_ptr; - zend_free_op free_op1; + zval *return_value; SAVE_OPLINE(); + return_value = EX(return_value); + do { if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) || (IS_TMP_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (!EX(return_value)) { - zval_ptr_dtor_nogc(free_op1); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (!return_value) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (IS_TMP_VAR == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } @@ -17943,8 +18649,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { } @@ -17952,17 +18658,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } } while (0); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -17970,12 +18677,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HAND { USE_OPLINE zval *retval; - zend_free_op free_op1; zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); - retval = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { @@ -18010,103 +18716,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HAND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - do { - if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { - if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - value = Z_REFVAL_P(value); - if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { - break; - } - } - if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - } - zend_throw_error(NULL, "Can only throw objects"); - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - } while (0); - - zend_exception_save(); - if (IS_TMP_VAR != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - - zend_throw_exception_object(value); - zend_exception_restore(); - - HANDLE_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - zend_free_op free_op1; - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(0)) { - if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_val_by_ref; - } - } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); - } - } - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value, *arg; - zend_free_op free_op1; - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(1)) { - if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_val_by_ref; - } - } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { - Z_ADDREF_P(arg); - } - } - ZEND_VM_NEXT_OPCODE(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *arg, *param; - zend_free_op free_op1; SAVE_OPLINE(); @@ -18114,31 +18727,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEN zend_param_must_be_ref(EX(call)->func, opline->op2.num); } - arg = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + arg = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); param = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY(param, arg); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); switch (opline->extended_value) { - case IS_NULL: - ZVAL_NULL(result); - break; - case _IS_BOOL: - ZVAL_BOOL(result, zend_is_true(expr)); - break; case IS_LONG: ZVAL_LONG(result, zval_get_long(expr)); break; @@ -18149,6 +18755,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC ZVAL_STR(result, zval_get_string(expr)); break; default: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); if (IS_TMP_VAR & (IS_VAR|IS_CV)) { ZVAL_DEREF(expr); } @@ -18191,6 +18798,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC } } } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); if (Z_TYPE_P(expr) == IS_ARRAY) { ht = zend_symtable_to_proptable(Z_ARR_P(expr)); @@ -18211,19 +18819,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC } } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *result; SAVE_OPLINE(); - array_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); @@ -18234,17 +18841,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (IS_TMP_VAR != IS_TMP_VAR) { @@ -18263,7 +18873,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE } else { zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } else if (is_empty) { @@ -18273,10 +18883,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -18284,7 +18894,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *array_ref; SAVE_OPLINE(); @@ -18295,7 +18904,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z array_ptr = Z_REFVAL_P(array_ref); } } else { - array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); } if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { @@ -18360,7 +18969,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z if (IS_TMP_VAR == IS_VAR) { } else { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); @@ -18371,13 +18980,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_TMP_VAR == IS_VAR) { } else { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@ -18387,7 +18996,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(Z { USE_OPLINE - if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); @@ -18396,13 +19006,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; - int ret; + bool ret; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { if (IS_TMP_VAR == IS_VAR) { @@ -18414,7 +19023,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ ret = i_zend_is_true(value); if (UNEXPECTED(EG(exception))) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -18439,19 +19048,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { if (IS_TMP_VAR & IS_VAR) { @@ -18479,18 +19087,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *result = EX_VAR(opline->result.var); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { SAVE_OPLINE(); ZVAL_UNDEFINED_OP1(); @@ -18522,146 +19129,48 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *op1, *op2; + zend_bool result; - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - zval *val; - zend_free_op free_op1; - - SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); - zval_ptr_dtor_nogc(free_op1); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (Z_TYPE_P(val) == IS_ARRAY) { - ZVAL_COPY_VALUE(&generator->values, val); - if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { - Z_ADDREF_P(val); - } - Z_FE_POS(generator->values) = 0; - - } else if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(val); - if (ce == zend_ce_generator) { - zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - - if (IS_TMP_VAR != IS_TMP_VAR) { - Z_ADDREF_P(val); - } - - if (Z_ISUNDEF(new_gen->retval)) { - if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { - zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } else { - zend_generator_yield_from(generator, new_gen); - } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } else { - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); - } - ZEND_VM_NEXT_OPCODE(); - } - } else { - zend_object_iterator *iter = ce->get_iterator(ce, val, 0); - zval_ptr_dtor_nogc(free_op1); - - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (!EG(exception)) { - zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); - } - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - } - - ZVAL_OBJ(&generator->values, &iter->std); - } - } else { - zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); - zval_ptr_dtor_nogc(free_op1); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - /* This is the default return value - * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* This generator has no send target (though the generator we delegate to might have one) */ - generator->send_target = NULL; - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_RETURN(); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18703,7 +19212,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var; @@ -18739,7 +19247,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var, *ret; uint32_t i; @@ -18793,10 +19300,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -18810,7 +19353,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON } } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_TMP_VAR == IS_CONST) { @@ -18835,7 +19378,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON } if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); zend_string *str; zend_ulong hval; @@ -18931,8 +19473,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z /* Set the new yielded value */ if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -18941,7 +19481,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -18973,7 +19513,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { @@ -19000,26 +19540,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -19055,13 +19580,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_TMP_VAR == IS_CONST); } else if (opline->extended_value) { @@ -19074,22 +19598,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLE result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } } ZEND_HASH_FOREACH_END(); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -19131,20 +19652,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TM static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var; /* op1 and result are the same */ rope = (zend_string**)EX_VAR(opline->op1.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); rope[opline->extended_value] = Z_STR_P(var); if (UNEXPECTED(Z_REFCOUNTED_P(var))) { Z_ADDREF_P(var); } } else { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); @@ -19157,7 +19677,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDL ZVAL_UNDEFINED_OP2(); } rope[opline->extended_value] = zval_get_string_func(var); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -19167,7 +19687,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var, *ret; uint32_t i; @@ -19176,13 +19695,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL rope = (zend_string**)EX_VAR(opline->op1.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); rope[opline->extended_value] = Z_STR_P(var); if (UNEXPECTED(Z_REFCOUNTED_P(var))) { Z_ADDREF_P(var); } } else { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); @@ -19195,7 +19714,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL ZVAL_UNDEFINED_OP2(); } rope[opline->extended_value] = zval_get_string_func(var); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (UNEXPECTED(EG(exception))) { for (i = 0; i <= opline->extended_value; i++) { zend_string_release_ex(rope[i], 0); @@ -19224,7 +19743,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -19238,7 +19756,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP } } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_TMP_VAR == IS_CONST) { @@ -19263,8 +19781,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; @@ -19309,7 +19826,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -19340,43 +19857,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HAN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -19395,8 +19876,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN /* Set the new yielded value */ if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -19405,7 +19884,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -19437,7 +19916,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { @@ -19463,27 +19942,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -19516,144 +19981,62 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *op1, *op2; + zend_bool result; SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = NULL; - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_TMP_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ SAVE_OPLINE(); - - ZEND_VM_RETURN(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -19677,58 +20060,149 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - SAVE_OPLINE(); if (IS_TMP_VAR == IS_UNUSED) { - zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_TMP_VAR != IS_UNUSED) + USE_OPLINE zval *retval_ref, *retval_ptr; - zend_free_op free_op1; zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - - retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CONST) { ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); retval_ref = retval_ptr = EX_VAR(opline->result.var); } else if (IS_TMP_VAR == IS_VAR) { if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { - retval_ptr = Z_INDIRECT_P(retval_ptr); + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); } ZVAL_DEREF(retval_ptr); } else if (IS_TMP_VAR == IS_CV) { ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(arg_num, arg ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -19742,7 +20216,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU } } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_TMP_VAR == IS_CONST) { @@ -19767,7 +20241,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU } if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -19863,8 +20336,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( /* Set the new yielded value */ if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -19873,7 +20344,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -19905,7 +20376,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { @@ -19932,26 +20403,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -19987,22 +20443,35 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; zend_string *type; SAVE_OPLINE(); - op1 = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - type = zend_zval_get_type(op1); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + type = zend_zval_get_legacy_type(op1); if (EXPECTED(type)) { ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); } else { ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 @@ -20042,7 +20511,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var; @@ -20078,7 +20546,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var, *ret; uint32_t i; @@ -20135,7 +20602,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -20149,7 +20615,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ } } else { - expr_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_TMP_VAR == IS_CONST) { @@ -20174,7 +20640,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ } if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); zend_string *str; zend_ulong hval; @@ -20270,8 +20735,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND /* Set the new yielded value */ if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -20280,7 +20743,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -20312,7 +20775,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND } } else { - zval *value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_TMP_VAR == IS_CONST) { @@ -20339,26 +20802,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -20394,10 +20842,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *closure, *var; - closure = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + closure = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); if (opline->extended_value & ZEND_BIND_REF) { /* By-ref binding */ var = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); @@ -20427,17 +20874,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDL static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { @@ -20461,17 +20900,16 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_increment_function(var_ptr); @@ -20487,10 +20925,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_R static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_increment_function(var_ptr); @@ -20506,17 +20943,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_R static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { @@ -20541,17 +20970,16 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_decrement_function(var_ptr); @@ -20567,10 +20995,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_R static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_decrement_function(var_ptr); @@ -20586,15 +21013,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_R static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { @@ -20617,17 +21038,16 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel increment_function(var_ptr); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); @@ -20641,15 +21061,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); SAVE_OPLINE(); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { @@ -20672,17 +21086,16 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel decrement_function(var_ptr); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); @@ -20698,10 +21111,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; - retval_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -20710,9 +21123,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } } else if (!return_value) { if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -20727,7 +21140,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { @@ -20763,6 +21176,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA } } } + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -20770,26 +21186,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER { USE_OPLINE zval *retval_ptr; - zend_free_op free_op1; + zval *return_value; SAVE_OPLINE(); + return_value = EX(return_value); + do { if ((IS_VAR & (IS_CONST|IS_TMP_VAR)) || (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (!EX(return_value)) { - zval_ptr_dtor_nogc(free_op1); + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (!return_value) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (IS_VAR == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } @@ -20797,33 +21215,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER break; } - retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } break; } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } while (0); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -20831,12 +21250,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND { USE_OPLINE zval *retval; - zend_free_op free_op1; zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); - retval = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Copy return value into generator->retval */ if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { @@ -20871,349 +21289,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *value; - zend_free_op free_op1; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - do { - if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { - if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - value = Z_REFVAL_P(value); - if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { - break; - } - } - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - } - zend_throw_error(NULL, "Can only throw objects"); - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - } while (0); - - zend_exception_save(); - if (IS_VAR != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - - zend_throw_exception_object(value); - zend_exception_restore(); - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); -} - -static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - zend_free_op free_op1; - - 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(); - ZVAL_UNDEFINED_OP1(); - 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_COPY_DEREF(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_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *varptr, *arg; - - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr))) { - ZEND_VM_NEXT_OPCODE(); - } - - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(0)) { - if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr) || - QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); - } - } else { - if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr) || - ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); - } - } - - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *varptr, *arg; - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(1)) { - if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr) || - QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); - } - } else { - if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - ZVAL_COPY_VALUE(arg, varptr); - - if (EXPECTED(Z_ISREF_P(varptr) || - ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { - ZEND_VM_NEXT_OPCODE(); - } - } - - SAVE_OPLINE(); - ZVAL_NEW_REF(arg, arg); - zend_error(E_NOTICE, "Only variables should be passed by reference"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *varptr, *arg; - - SAVE_OPLINE(); - varptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(varptr))) { - ZVAL_NEW_EMPTY_REF(arg); - ZVAL_NULL(Z_REFVAL_P(arg)); - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_ISREF_P(varptr)) { - Z_ADDREF_P(varptr); - } else { - ZVAL_MAKE_REF_EX(varptr, 2); - } - ZVAL_REF(arg, Z_REF_P(varptr)); - - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - zend_free_op free_op1; - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(0)) { - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var_by_ref; - } - } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_var_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(); - ZVAL_UNDEFINED_OP1(); - 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_COPY_DEREF(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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - zend_free_op free_op1; - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(1)) { - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var_by_ref; - } - } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_var_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(); - ZVAL_UNDEFINED_OP1(); - 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_COPY_DEREF(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_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); - arg = ZEND_CALL_VAR(EX(call), opline->result.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 zval *arg, *param; - zend_free_op free_op1; SAVE_OPLINE(); @@ -21221,31 +21300,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN zend_param_must_be_ref(EX(call)->func, opline->op2.num); } - arg = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + arg = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); param = ZEND_CALL_VAR(EX(call), opline->result.var); ZVAL_COPY(param, arg); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); switch (opline->extended_value) { - case IS_NULL: - ZVAL_NULL(result); - break; - case _IS_BOOL: - ZVAL_BOOL(result, zend_is_true(expr)); - break; case IS_LONG: ZVAL_LONG(result, zval_get_long(expr)); break; @@ -21256,6 +21328,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC ZVAL_STR(result, zval_get_string(expr)); break; default: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); if (IS_VAR & (IS_VAR|IS_CV)) { ZVAL_DEREF(expr); } @@ -21268,7 +21341,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -21299,6 +21372,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC } } } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); if (Z_TYPE_P(expr) == IS_ARRAY) { ht = zend_symtable_to_proptable(Z_ARR_P(expr)); @@ -21319,19 +21393,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC } } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *result; SAVE_OPLINE(); - array_ptr = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ptr = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); @@ -21340,20 +21413,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE } Z_FE_POS_P(result) = 0; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (IS_VAR != IS_TMP_VAR) { @@ -21362,17 +21438,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(result) = (uint32_t) -1; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } else if (is_empty) { @@ -21382,10 +21458,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@ -21393,18 +21469,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *array_ptr, *array_ref; SAVE_OPLINE(); if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { - array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(array_ref)) { array_ptr = Z_REFVAL_P(array_ref); } } else { - array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); } if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { @@ -21428,7 +21503,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); if (IS_VAR == IS_VAR) { - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { @@ -21456,20 +21531,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z properties = Z_OBJPROP_P(array_ptr); if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); @@ -21480,13 +21555,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_VAR == IS_VAR) { - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@ -21515,6 +21590,7 @@ fe_fetch_r_exit: ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); } + pos++; value = &p->val; value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF)) { @@ -21528,10 +21604,9 @@ fe_fetch_r_exit: break; } } - pos++; p++; } - Z_FE_POS_P(array) = pos + 1; + Z_FE_POS_P(array) = pos; if (RETURN_VALUE_USED(opline)) { if (!p->key) { ZVAL_LONG(EX_VAR(opline->result.var), p->h); @@ -21554,7 +21629,7 @@ fe_fetch_r_exit: /* reached end of iteration */ goto fe_fetch_r_exit; } - + pos++; value = &p->val; value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF)) { @@ -21571,9 +21646,9 @@ fe_fetch_r_exit: break; } } - pos++; p++; } + EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos; if (RETURN_VALUE_USED(opline)) { if (UNEXPECTED(!p->key)) { ZVAL_LONG(EX_VAR(opline->result.var), p->h); @@ -21587,7 +21662,6 @@ fe_fetch_r_exit: ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len); } } - EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos + 1; } else { if (EXPECTED(++iter->index > 0)) { /* This could cause an endless loop if index becomes zero again. @@ -21668,6 +21742,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z /* reached end of iteration */ goto fe_fetch_w_exit; } + pos++; value = &p->val; value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF)) { @@ -21681,9 +21756,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z break; } } - pos++; p++; } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; if (RETURN_VALUE_USED(opline)) { if (!p->key) { ZVAL_LONG(EX_VAR(opline->result.var), p->h); @@ -21691,7 +21766,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); } } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { zend_object_iterator *iter; @@ -21706,7 +21780,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z /* reached end of iteration */ goto fe_fetch_w_exit; } - + pos++; value = &p->val; value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF)) { @@ -21732,9 +21806,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z break; } } - pos++; p++; } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; if (RETURN_VALUE_USED(opline)) { if (UNEXPECTED(!p->key)) { ZVAL_LONG(EX_VAR(opline->result.var), p->h); @@ -21748,7 +21822,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len); } } - EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; } else { if (++iter->index > 0) { /* This could cause an endless loop if index becomes zero again. @@ -21790,7 +21863,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z value_type = Z_TYPE_INFO_P(value); } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array)); if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -21827,13 +21900,12 @@ fe_fetch_w_exit: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; - int ret; + bool ret; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { if (IS_VAR == IS_VAR) { @@ -21845,7 +21917,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_ ret = i_zend_is_true(value); if (UNEXPECTED(EG(exception))) { - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -21870,19 +21942,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_ ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *ref = NULL; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { if (IS_VAR & IS_VAR) { @@ -21910,18 +21981,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *result = EX_VAR(opline->result.var); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { SAVE_OPLINE(); ZVAL_UNDEFINED_OP1(); @@ -21953,121 +22023,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - zval *val; - zend_free_op free_op1; - - SAVE_OPLINE(); - val = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); - zval_ptr_dtor_nogc(free_op1); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (Z_TYPE_P(val) == IS_ARRAY) { - ZVAL_COPY_VALUE(&generator->values, val); - if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { - Z_ADDREF_P(val); - } - Z_FE_POS(generator->values) = 0; - - zval_ptr_dtor_nogc(free_op1); - } else if (IS_VAR != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { - zend_class_entry *ce = Z_OBJCE_P(val); - if (ce == zend_ce_generator) { - zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - - if (IS_VAR != IS_TMP_VAR) { - Z_ADDREF_P(val); - } - zval_ptr_dtor_nogc(free_op1); - - if (Z_ISUNDEF(new_gen->retval)) { - if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { - zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } else { - zend_generator_yield_from(generator, new_gen); - } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } else { - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); - } - ZEND_VM_NEXT_OPCODE(); - } - } else { - zend_object_iterator *iter = ce->get_iterator(ce, val, 0); - zval_ptr_dtor_nogc(free_op1); - - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (!EG(exception)) { - zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); - } - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - } - - ZVAL_OBJ(&generator->values, &iter->std); - } - } else { - zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); - zval_ptr_dtor_nogc(free_op1); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - /* This is the default return value - * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* This generator has no send target (though the generator we delegate to might have one) */ - generator->send_target = NULL; - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; - zend_free_op free_op1; - varptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (IS_VAR == IS_CV) { @@ -22079,87 +22040,68 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SP ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *varptr, *arg; - zend_free_op free_op1; - uint32_t arg_num = opline->op2.num; - - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - 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); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); + zval *op1, *op2; + zend_bool result; - if (IS_VAR == IS_CV) { - ZVAL_COPY(arg, varptr); - } else /* if (IS_VAR == IS_VAR) */ { - ZVAL_COPY_VALUE(arg, varptr); - } + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -22170,16 +22112,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_H && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22216,13 +22166,16 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -22231,12 +22184,11 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data1; zval *var_ptr; zval *value, *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: @@ -22260,7 +22212,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -22277,7 +22229,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -22302,71 +22254,60 @@ assign_dim_op_new_array: } else { zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); assign_dim_op_ret_null: - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; zval *value; SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op2); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); do { @@ -22379,16 +22320,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HAN && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22402,31 +22351,30 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); do { @@ -22439,16 +22387,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -22461,27 +22417,28 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22489,16 +22446,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22525,16 +22480,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22542,16 +22495,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -22560,7 +22508,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HAN BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22568,21 +22516,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22607,22 +22550,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22630,11 +22567,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = RT_CONSTANT(opline, opline->op2); if (IS_VAR == IS_VAR @@ -22653,16 +22589,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -22671,16 +22603,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -22770,16 +22701,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -22788,34 +22734,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -22905,16 +22846,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -22923,34 +22879,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23040,16 +22991,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23058,16 +23024,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -23076,16 +23038,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23175,16 +23136,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23193,21 +23169,19 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = RT_CONSTANT((opline+1), (opline+1)->op1); SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); } @@ -23220,11 +23194,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -23241,6 +23216,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = RT_CONSTANT((opline+1), (opline+1)->op1); value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -23285,9 +23261,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: @@ -23299,7 +23273,7 @@ assign_dim_error: if (IS_CONST != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23307,21 +23281,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -23334,6 +23306,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -23355,6 +23328,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -23369,14 +23343,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -23384,9 +23358,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -23400,9 +23374,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -23414,7 +23386,7 @@ assign_dim_error: if (IS_CONST != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23422,21 +23394,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -23449,6 +23419,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -23470,6 +23441,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -23484,14 +23456,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -23499,9 +23471,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -23515,9 +23487,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -23529,7 +23499,7 @@ assign_dim_error: if (IS_CONST != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23537,21 +23507,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); } @@ -23564,11 +23532,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -23585,6 +23554,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -23629,9 +23599,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: @@ -23643,7 +23611,7 @@ assign_dim_error: if (IS_CONST != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23651,27 +23619,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -23679,27 +23639,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op2); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -23707,20 +23659,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_VAR == IS_UNUSED) { @@ -23740,9 +23686,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_ zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -23750,17 +23696,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = RT_CONSTANT(opline, opline->op2); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -23783,7 +23723,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_ zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -23807,7 +23747,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -23818,7 +23757,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } else if (IS_VAR == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -23835,8 +23773,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { - - function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -23852,7 +23788,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -23872,7 +23808,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -23903,13 +23838,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -23931,6 +23862,299 @@ check_parent_and_self: ZEND_VM_NEXT_OPCODE(); } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(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_VAR_NO_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr))) { + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + 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)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } else { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + +send_var: + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + 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_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + 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)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + // TODO: Would it make sense to share the cache slot with CHECK_FUNC_ARG? + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + 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_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry *ce, *scope; @@ -23950,7 +24174,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ } else { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -23959,7 +24182,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (IS_VAR == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -23977,7 +24199,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ c = Z_PTR_P(zv); scope = EX(func)->op_array.scope; if (!zend_verify_const_access(c, scope)) { - zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -23991,7 +24213,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ } CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); } else { - zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -24005,21 +24228,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(expr_ptr)) { Z_ADDREF_P(expr_ptr); } else { ZVAL_MAKE_REF_EX(expr_ptr, 2); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_VAR == IS_CONST) { @@ -24044,7 +24266,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON } if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); zend_string *str; zend_ulong hval; @@ -24124,14 +24345,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; zval *offset; zend_ulong hval; zend_string *key; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); do { @@ -24182,7 +24402,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -24201,28 +24421,25 @@ num_index_dim: if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = RT_CONSTANT(opline, opline->op2); do { @@ -24240,10 +24457,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24266,8 +24494,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -24276,7 +24502,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -24284,7 +24510,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z } } } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ @@ -24306,10 +24532,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { @@ -24321,7 +24547,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z ZVAL_COPY_VALUE(&generator->value, value); } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CV) { @@ -24336,26 +24562,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -24391,13 +24602,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_VAR == IS_CONST); } else if (opline->extended_value) { @@ -24410,46 +24620,39 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLE result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } } ZEND_HASH_FOREACH_END(); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -24460,16 +24663,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_ && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -24506,13 +24717,16 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -24521,18 +24735,17 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data1; zval *var_ptr; zval *value, *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); assign_dim_op_new_array: - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { @@ -24550,7 +24763,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -24567,7 +24780,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -24576,7 +24789,7 @@ assign_dim_op_new_array: } } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -24592,74 +24805,63 @@ assign_dim_op_new_array: } else { zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); assign_dim_op_ret_null: - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *var_ptr; zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -24671,16 +24873,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -24694,33 +24904,32 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -24732,16 +24941,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_H && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -24754,28 +24971,29 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24783,16 +25001,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24819,16 +25035,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TM static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24836,25 +25050,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24862,21 +25071,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24901,22 +25105,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TM static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *property, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24924,12 +25122,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_VAR == IS_VAR && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT @@ -24941,24 +25138,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_H zend_fetch_dimension_address_W(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -24966,16 +25159,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25065,16 +25257,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25083,34 +25290,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25200,16 +25402,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25218,34 +25435,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25335,16 +25547,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25353,17 +25580,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -25371,16 +25594,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -25470,16 +25692,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25488,21 +25725,19 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = RT_CONSTANT((opline+1), (opline+1)->op1); SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); } @@ -25515,11 +25750,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -25527,7 +25763,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -25536,6 +25772,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = RT_CONSTANT((opline+1), (opline+1)->op1); value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25549,7 +25786,7 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -25563,7 +25800,7 @@ try_assign_dim_array: UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -25572,7 +25809,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -25580,10 +25817,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25592,9 +25827,9 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25602,21 +25837,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -25629,6 +25862,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -25641,7 +25875,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -25650,6 +25884,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25663,31 +25898,31 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -25695,10 +25930,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25707,9 +25940,9 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25717,21 +25950,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -25744,6 +25975,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -25756,7 +25988,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -25765,6 +25997,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25778,31 +26011,31 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -25810,10 +26043,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25822,9 +26053,9 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25832,21 +26063,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); } @@ -25859,11 +26088,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -25871,7 +26101,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -25880,6 +26110,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25893,7 +26124,7 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -25907,7 +26138,7 @@ try_assign_dim_array: UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -25916,7 +26147,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -25924,10 +26155,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -25936,9 +26165,9 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25946,20 +26175,14 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_VAR == IS_UNUSED) { @@ -25979,9 +26202,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -25989,18 +26212,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -26022,8 +26239,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -26046,7 +26263,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -26057,7 +26273,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } else if (IS_VAR == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -26074,9 +26289,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { @@ -26091,8 +26304,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } @@ -26107,11 +26320,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (EXPECTED(!EG(exception))) { zend_undefined_method(ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -26119,7 +26331,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V init_func_run_time_cache(&fbc->op_array); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -26142,13 +26354,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -26173,21 +26381,20 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(expr_ptr)) { Z_ADDREF_P(expr_ptr); } else { ZVAL_MAKE_REF_EX(expr_ptr, 2); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_VAR == IS_CONST) { @@ -26212,8 +26419,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; @@ -26258,7 +26464,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -26292,15 +26498,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; zval *offset; zend_ulong hval; zend_string *key; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -26350,7 +26555,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -26369,30 +26574,27 @@ num_index_dim: if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } } while (0); - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { @@ -26409,107 +26611,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); - } while (0); - - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1, free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } + } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26528,8 +26649,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -26538,7 +26657,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -26546,7 +26665,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN } } } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ @@ -26568,10 +26687,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { @@ -26583,7 +26702,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN ZVAL_COPY_VALUE(&generator->value, value); } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CV) { @@ -26597,27 +26716,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -26650,66 +26755,150 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26717,27 +26906,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNU static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26745,23 +26926,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *variable_ptr; zval *value_ptr; SAVE_OPLINE(); - value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && + if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -26777,161 +26953,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } - if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_VAR == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - } - } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data1; zval *var_ptr; zval *value, *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: @@ -26955,7 +26989,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -26972,7 +27006,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -26997,30 +27031,28 @@ assign_dim_op_new_array: } else { zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); assign_dim_op_ret_null: - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27028,16 +27060,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27064,21 +27094,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = RT_CONSTANT((opline+1), (opline+1)->op1); SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); } @@ -27091,11 +27119,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -27112,6 +27141,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = RT_CONSTANT((opline+1), (opline+1)->op1); value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -27156,9 +27186,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: @@ -27170,7 +27198,7 @@ assign_dim_error: if (IS_UNUSED != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -27178,21 +27206,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -27205,6 +27231,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -27226,6 +27253,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -27240,14 +27268,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -27255,9 +27283,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -27271,9 +27299,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -27285,7 +27311,7 @@ assign_dim_error: if (IS_UNUSED != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -27293,21 +27319,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -27320,6 +27344,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -27341,6 +27366,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -27355,14 +27381,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -27370,9 +27396,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -27386,9 +27412,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -27400,7 +27424,7 @@ assign_dim_error: if (IS_UNUSED != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -27408,21 +27432,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); } @@ -27435,11 +27457,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -27456,6 +27479,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -27500,9 +27524,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: @@ -27514,7 +27536,7 @@ assign_dim_error: if (IS_UNUSED != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -27536,7 +27558,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -27547,7 +27568,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } else if (IS_VAR == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -27564,8 +27584,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { - - function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -27581,7 +27599,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -27601,7 +27619,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -27632,13 +27649,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -27662,52 +27675,497 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - SAVE_OPLINE(); if (IS_VAR == IS_UNUSED) { - zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_VAR != IS_UNUSED) + USE_OPLINE zval *retval_ref, *retval_ptr; - zend_free_op free_op1; zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - - retval_ref = retval_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ref = retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CONST) { ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); retval_ref = retval_ptr = EX_VAR(opline->result.var); } else if (IS_VAR == IS_VAR) { if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { - retval_ptr = Z_INDIRECT_P(retval_ptr); + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); } ZVAL_DEREF(retval_ptr); } else if (IS_VAR == IS_CV) { ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(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_VAR_NO_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr))) { + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } else { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + +send_var: + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } else { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + +send_var: + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + 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_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + SAVE_OPLINE(); + if (IS_UNUSED == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_UNUSED == IS_CONST) { + // TODO: Would it make sense to share the cache slot with CHECK_FUNC_ARG? + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + 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_NEW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -27724,7 +28182,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -27733,7 +28190,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE } else if (IS_VAR == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -27784,21 +28240,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(expr_ptr)) { Z_ADDREF_P(expr_ptr); } else { ZVAL_MAKE_REF_EX(expr_ptr, 2); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_VAR == IS_CONST) { @@ -27823,7 +28278,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU } if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -27934,8 +28388,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -27944,7 +28396,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -27952,7 +28404,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( } } } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ @@ -27974,10 +28426,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { @@ -27989,7 +28441,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( ZVAL_COPY_VALUE(&generator->value, value); } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CV) { @@ -28004,26 +28456,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -28092,44 +28529,75 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *op1; zend_string *type; SAVE_OPLINE(); - op1 = _get_zval_ptr_var_deref(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - type = zend_zval_get_type(op1); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + type = zend_zval_get_legacy_type(op1); if (EXPECTED(type)) { ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); } else { ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); } - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; + + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -28140,16 +28608,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HAND && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -28186,13 +28662,16 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -28201,12 +28680,11 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data1; zval *var_ptr; zval *value, *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: @@ -28230,7 +28708,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -28247,7 +28725,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -28272,71 +28750,60 @@ assign_dim_op_new_array: } else { zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); assign_dim_op_ret_null: - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *var_ptr; zval *value; SAVE_OPLINE(); value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -28349,16 +28816,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLE && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -28372,31 +28847,30 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -28409,16 +28883,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDL && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -28431,27 +28913,28 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28459,16 +28942,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28495,16 +28976,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28512,16 +28991,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -28530,7 +29004,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLE BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28538,21 +29012,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28577,22 +29046,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_VAR == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -28600,11 +29063,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *dim; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); dim = EX_VAR(opline->op2.var); if (IS_VAR == IS_VAR @@ -28623,16 +29085,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -28641,16 +29099,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -28740,16 +29197,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -28758,34 +29230,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -28875,16 +29342,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -28893,34 +29375,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -29010,16 +29487,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29028,16 +29520,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -29046,16 +29534,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -29145,16 +29632,31 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29163,21 +29665,19 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = RT_CONSTANT((opline+1), (opline+1)->op1); SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); } @@ -29190,11 +29690,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -29211,6 +29712,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = RT_CONSTANT((opline+1), (opline+1)->op1); value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -29255,9 +29757,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: @@ -29269,7 +29769,7 @@ assign_dim_error: if (IS_CV != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29277,21 +29777,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -29304,6 +29802,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -29325,6 +29824,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -29339,14 +29839,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -29354,9 +29854,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -29370,9 +29870,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -29384,7 +29882,7 @@ assign_dim_error: if (IS_CV != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29392,21 +29890,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -29419,6 +29915,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -29440,6 +29937,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -29454,14 +29952,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -29469,9 +29967,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -29485,9 +29983,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -29499,7 +29995,7 @@ assign_dim_error: if (IS_CV != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29507,21 +30003,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; SAVE_OPLINE(); - orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); } @@ -29534,11 +30028,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -29555,6 +30050,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -29599,9 +30095,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_VAR != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: @@ -29613,7 +30107,7 @@ assign_dim_error: if (IS_CV != IS_UNUSED) { } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29621,27 +30115,19 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -29649,27 +30135,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *value; zval *variable_ptr; SAVE_OPLINE(); value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -29677,23 +30155,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *variable_ptr; zval *value_ptr; SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && + if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -29709,27 +30182,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_VAR == IS_UNUSED) { @@ -29749,9 +30216,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_ zend_assign_to_property_reference(container, IS_VAR, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -29759,17 +30226,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *value_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -29792,7 +30253,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_ zend_assign_to_property_reference(container, IS_VAR, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -29816,7 +30277,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -29827,7 +30287,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } else if (IS_VAR == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -29844,8 +30303,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { - - function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -29861,7 +30318,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -29881,7 +30338,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -29912,13 +30368,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_VAR == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -29943,21 +30395,20 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *expr_ptr, new_expr; SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { - expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (Z_ISREF_P(expr_ptr)) { Z_ADDREF_P(expr_ptr); } else { ZVAL_MAKE_REF_EX(expr_ptr, 2); } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { - expr_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_TMP_VAR) { /* pass */ } else if (IS_VAR == IS_CONST) { @@ -29982,7 +30433,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ } if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); zend_string *str; zend_ulong hval; @@ -30062,14 +30512,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; zval *offset; zend_ulong hval; zend_string *key; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = EX_VAR(opline->op2.var); do { @@ -30120,7 +30569,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -30139,28 +30588,25 @@ num_index_dim: if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -30178,10 +30624,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER( break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30204,8 +30661,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND /* Set the new yielded value */ if (IS_VAR != IS_UNUSED) { - zend_free_op free_op1; - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -30214,7 +30669,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { @@ -30222,7 +30677,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND } } } else { - zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ @@ -30244,10 +30699,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } } else { - zval *value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); /* Consts, temporary variables and references need copying */ if (IS_VAR == IS_CONST) { @@ -30259,7 +30714,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND ZVAL_COPY_VALUE(&generator->value, value); } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_VAR == IS_CV) { @@ -30274,26 +30729,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -30347,6 +30787,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); } + pos++; value = &p->val; value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF)) { @@ -30360,10 +30801,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ break; } } - pos++; p++; } - Z_FE_POS_P(array) = pos + 1; + Z_FE_POS_P(array) = pos; if (0) { if (!p->key) { ZVAL_LONG(EX_VAR(opline->result.var), p->h); @@ -30399,6 +30839,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); } + pos++; value = &p->val; value_type = Z_TYPE_INFO_P(value); if (EXPECTED(value_type != IS_UNDEF)) { @@ -30412,10 +30853,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ break; } } - pos++; p++; } - Z_FE_POS_P(array) = pos + 1; + Z_FE_POS_P(array) = pos; if (1) { if (!p->key) { ZVAL_LONG(EX_VAR(opline->result.var), p->h); @@ -30430,49 +30870,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ } -static 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_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -30480,10 +30882,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND SAVE_OPLINE(); obj = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - do { if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { @@ -30506,9 +30904,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -30529,7 +30928,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30540,12 +30939,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_H zend_class_entry *called_scope, *scope; USE_OPLINE - fetch_type = opline->op1.num; + if (IS_UNUSED != IS_UNUSED) { + zval *op = NULL; + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_OBJECT) { + zend_type_error("Cannot use \"::class\" on value of type %s", zend_zval_type_name(op)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + HANDLE_EXCEPTION(); + } + } + + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + fetch_type = opline->op1.num; scope = EX(func)->op_array.scope; if (UNEXPECTED(scope == NULL)) { SAVE_OPLINE(); - zend_throw_error(NULL, "Cannot use \"%s\" when no class scope is active", + zend_throw_error(NULL, "Cannot use \"%s\" in the global scope", fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -30582,25 +30998,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -30611,16 +31023,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONS && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -30657,11 +31077,14 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_obj has two opcodes! */ @@ -30672,20 +31095,16 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { @@ -30698,16 +31117,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_ && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -30721,7 +31148,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -30732,20 +31162,16 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { @@ -30758,16 +31184,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -30780,7 +31214,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -30791,19 +31228,12 @@ post_incdec_object: static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_UNUSED == IS_CONST || @@ -30821,7 +31251,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -30830,9 +31260,11 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -30857,10 +31289,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -30871,7 +31303,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -30883,11 +31315,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -30911,16 +31354,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -30929,7 +31367,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_ BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30937,21 +31375,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30959,19 +31392,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_UNUSED == IS_CONST || @@ -30991,9 +31417,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -31018,10 +31446,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -31032,7 +31460,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -31044,9 +31472,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -31082,22 +31520,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -31105,16 +31537,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -31123,16 +31551,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -31222,11 +31649,26 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: @@ -31240,34 +31682,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -31357,13 +31794,28 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: @@ -31375,34 +31827,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -31492,13 +31939,28 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: @@ -31510,16 +31972,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -31528,16 +31986,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -31627,11 +32084,26 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: @@ -31645,20 +32117,14 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_UNUSED == IS_UNUSED) { @@ -31679,7 +32145,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CON } - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -31687,17 +32153,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -31729,7 +32189,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var; @@ -31764,7 +32223,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *class_name; USE_OPLINE @@ -31809,7 +32267,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -31821,10 +32278,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S object = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CONST != IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); } @@ -31851,12 +32304,26 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } while (0); } - if (IS_UNUSED != IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_UNUSED & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -31880,7 +32347,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if (IS_CONST == IS_CONST && @@ -31900,18 +32366,21 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -31924,9 +32393,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -31934,9 +32405,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -31967,7 +32435,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -31978,7 +32445,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } else if (IS_UNUSED == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -31995,8 +32461,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { - - function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -32012,7 +32476,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -32032,7 +32496,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -32063,13 +32526,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -32091,6 +32550,38 @@ check_parent_and_self: ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg_num = zend_get_arg_offset_by_name( + EX(call)->func, arg_name, CACHE_ADDR(opline->result.num)) + 1; + if (UNEXPECTED(arg_num == 0)) { + /* Treat this as a by-value argument, and throw an error during SEND. */ + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + ZEND_VM_NEXT_OPCODE(); + } + } else { + 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(); +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -32126,7 +32617,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS } else { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -32135,7 +32625,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS if (IS_UNUSED == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -32153,7 +32642,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS c = Z_PTR_P(zv); scope = EX(func)->op_array.scope; if (!zend_verify_const_access(c, scope)) { - zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -32167,7 +32656,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS } CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); } else { - zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -32202,15 +32692,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } offset = RT_CONSTANT(opline, opline->op2); do { @@ -32228,7 +32715,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -32238,18 +32736,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_UNUSED == IS_CONST || @@ -32266,16 +32759,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -32297,8 +32802,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE /* Set the new yielded value */ if (IS_UNUSED != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -32366,26 +32869,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -32421,25 +32909,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -32450,16 +32934,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32496,12 +32988,15 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); - zval_ptr_dtor_nogc(free_op2); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -32511,21 +33006,17 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -32537,16 +33028,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32560,11 +33059,14 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32572,21 +33074,17 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -32598,16 +33096,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -32620,11 +33126,14 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32632,20 +33141,13 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -32662,7 +33164,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -32671,9 +33173,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -32698,10 +33202,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -32712,7 +33216,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -32724,11 +33228,22 @@ fetch_obj_r_fast_copy: } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -32739,7 +33254,7 @@ fetch_obj_r_copy: } while (0); fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32747,25 +33262,20 @@ fetch_obj_r_finish: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32773,21 +33283,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32795,20 +33300,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -32827,9 +33325,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -32854,10 +33354,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -32868,7 +33368,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -32880,9 +33380,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -32893,7 +33403,7 @@ fetch_obj_is_copy: } while (0); fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32918,22 +33428,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *property, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32941,17 +33445,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TM static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -32959,16 +33459,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33058,15 +33557,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -33076,34 +33590,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33193,15 +33702,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -33211,34 +33735,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33328,15 +33847,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -33346,17 +33880,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -33364,16 +33894,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33463,15 +33992,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -33481,20 +34025,14 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_UNUSED == IS_UNUSED) { @@ -33514,8 +34052,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP zend_assign_to_property_reference(container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -33523,18 +34061,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -33556,7 +34088,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP zend_assign_to_property_reference(container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -33565,20 +34097,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zend_string **rope; zval *var; /* Compiler allocates the necessary number of zval slots to keep the rope */ rope = (zend_string**)EX_VAR(opline->result.var); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); rope[0] = Z_STR_P(var); if (UNEXPECTED(Z_REFCOUNTED_P(var))) { Z_ADDREF_P(var); } } else { - var = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { rope[0] = zend_string_copy(Z_STR_P(var)); @@ -33591,7 +34122,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_H ZVAL_UNDEFINED_OP2(); } rope[0] = zval_get_string_func(var); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -33600,7 +34131,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zend_free_op free_op2; zval *class_name; USE_OPLINE @@ -33612,13 +34142,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR zend_class_entry *ce = CACHED_PTR(opline->extended_value); if (UNEXPECTED(ce == NULL)) { - class_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + class_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), opline->op1.num); CACHE_PTR(opline->extended_value, ce); } Z_CE_P(EX_VAR(opline->result.var)) = ce; } else { - class_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + class_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); try_class_name: if (Z_TYPE_P(class_name) == IS_OBJECT) { Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name); @@ -33638,7 +34168,7 @@ try_class_name: } } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -33646,7 +34176,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -33658,12 +34187,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T object = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST && @@ -33682,18 +34207,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } - if (IS_UNUSED != IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_UNUSED & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -33701,23 +34240,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if ((IS_TMP_VAR|IS_VAR) == IS_CONST && @@ -33727,7 +34265,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ @@ -33736,19 +34274,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); - + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -33756,14 +34297,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -33771,9 +34314,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -33804,7 +34344,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -33815,7 +34354,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } else if (IS_UNUSED == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } @@ -33832,9 +34370,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { @@ -33849,8 +34385,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } @@ -33865,11 +34401,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U if (EXPECTED(!EG(exception))) { zend_undefined_method(ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -33877,7 +34412,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U init_func_run_time_cache(&fbc->op_array); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -33900,13 +34435,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -33952,16 +34483,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { @@ -33978,10 +34506,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -33989,19 +34528,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -34017,159 +34551,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } - result = - (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); - -isset_object_finish: - zval_ptr_dtor_nogc(free_op2); - - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_UNUSED != IS_UNUSED) { - - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = NULL; - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = NULL; - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_UNUSED == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); } - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); +isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_RETURN(); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -34188,8 +34594,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( /* Set the new yielded value */ if (IS_UNUSED != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -34256,27 +34660,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( } /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -34311,7 +34701,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *class_name; USE_OPLINE @@ -34369,7 +34758,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -34380,7 +34768,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } else if (IS_UNUSED == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -34397,8 +34784,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { - - function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -34414,7 +34799,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -34434,7 +34819,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -34465,13 +34849,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -34495,18 +34875,16 @@ check_parent_and_self: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - SAVE_OPLINE(); if (IS_UNUSED == IS_UNUSED) { - zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_UNUSED != IS_UNUSED) + USE_OPLINE zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - retval_ref = retval_ptr = NULL; if (IS_UNUSED == IS_CONST) { @@ -34514,32 +34892,130 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED retval_ref = retval_ptr = EX_VAR(opline->result.var); } else if (IS_UNUSED == IS_VAR) { if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { - retval_ptr = Z_INDIRECT_P(retval_ptr); + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); } ZVAL_DEREF(retval_ptr); } else if (IS_UNUSED == IS_CV) { ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg_num = zend_get_arg_offset_by_name( + EX(call)->func, arg_name, CACHE_ADDR(opline->result.num)) + 1; + if (UNEXPECTED(arg_num == 0)) { + /* Treat this as a by-value argument, and throw an error during SEND. */ + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + ZEND_VM_NEXT_OPCODE(); + } + } else { + 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_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg_num = zend_get_arg_offset_by_name( + EX(call)->func, arg_name, CACHE_ADDR(opline->result.num)) + 1; + if (UNEXPECTED(arg_num == 0)) { + /* Treat this as a by-value argument, and throw an error during SEND. */ + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + ZEND_VM_NEXT_OPCODE(); + } + } else { + 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_execute_data *call = execute_data->call; + if (EXPECTED(!(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF))) { + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + zend_handle_undef_args(call); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -34557,7 +35033,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -34566,7 +35041,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER } else if (IS_UNUSED == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -34654,8 +35128,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL /* Set the new yielded value */ if (IS_UNUSED != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -34723,26 +35195,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -34775,7 +35232,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -34807,15 +35264,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_H if (IS_UNUSED == IS_UNUSED) { if (UNEXPECTED(!EX(func)->common.scope)) { SAVE_OPLINE(); - zend_error(E_WARNING, "get_class() called without object from outside a class"); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } else { ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); ZEND_VM_NEXT_OPCODE(); } } else { - zval *op1; SAVE_OPLINE(); @@ -34830,8 +35286,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_H if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_type_name(op1)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } @@ -34849,12 +35305,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CALLED_CLASS_SPEC_UNUSED_U } else if (Z_CE(EX(This))) { ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_CE(EX(This))->name); } else { - ZVAL_FALSE(EX_VAR(opline->result.var)); - if (UNEXPECTED(!EX(func)->common.scope)) { - SAVE_OPLINE(); - zend_error(E_WARNING, "get_called_class() called from outside a class"); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } + ZEND_ASSERT(!EX(func)->common.scope); + SAVE_OPLINE(); + zend_throw_error(NULL, "get_called_class() must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); } @@ -34945,25 +35400,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUS static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -34974,16 +35425,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_H && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -35020,11 +35479,14 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_obj has two opcodes! */ @@ -35035,20 +35497,16 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -35061,16 +35519,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HAN && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -35084,7 +35550,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -35095,20 +35564,16 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -35121,16 +35586,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -35143,7 +35616,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -35154,19 +35630,12 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = EX_VAR(opline->op2.var); if (IS_UNUSED == IS_CONST || @@ -35184,7 +35653,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -35193,9 +35662,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -35220,10 +35691,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -35234,7 +35705,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -35246,11 +35717,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -35269,16 +35751,11 @@ fetch_obj_r_finish: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -35287,7 +35764,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HAN BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -35295,21 +35772,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -35317,19 +35789,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || @@ -35349,9 +35814,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -35376,10 +35843,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -35390,7 +35857,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -35402,9 +35869,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -35440,22 +35917,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_UNUSED == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -35463,16 +35934,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -35481,16 +35948,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35580,11 +36046,26 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: @@ -35598,34 +36079,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35715,13 +36191,28 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: @@ -35733,34 +36224,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35850,13 +36336,28 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: @@ -35868,16 +36369,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -35886,16 +36383,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35985,11 +36481,26 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: @@ -36003,20 +36514,14 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_UNUSED == IS_UNUSED) { @@ -36037,7 +36542,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_ } - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -36045,17 +36550,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -36087,7 +36586,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string **rope; zval *var; @@ -36122,7 +36620,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zval *class_name; USE_OPLINE @@ -36167,7 +36664,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -36179,10 +36675,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C object = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CV != IS_CONST) { function_name = EX_VAR(opline->op2.var); } @@ -36209,12 +36701,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } while (0); } - if (IS_UNUSED != IS_UNUSED) { + if (IS_UNUSED == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_UNUSED & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -36238,7 +36744,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if (IS_CV == IS_CONST && @@ -36258,18 +36763,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -36282,9 +36790,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -36292,9 +36802,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -36325,7 +36832,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -36336,7 +36842,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } else if (IS_UNUSED == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); HANDLE_EXCEPTION(); } @@ -36353,8 +36858,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U EXPECTED(CACHED_PTR(opline->result.num) == ce)) { fbc = CACHED_PTR(opline->result.num + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { - - function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -36370,7 +36873,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Method name must be a string"); HANDLE_EXCEPTION(); } while (0); @@ -36390,7 +36893,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -36421,13 +36923,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - goto check_parent_and_self; + HANDLE_EXCEPTION(); } } else { -check_parent_and_self: /* previous opcode is ZEND_FETCH_CLASS */ if (IS_UNUSED == IS_UNUSED && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || @@ -36473,15 +36971,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -36499,7 +36994,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -36509,18 +37015,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST || @@ -36537,16 +37038,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -36568,8 +37081,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z /* Set the new yielded value */ if (IS_UNUSED != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -36637,26 +37148,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -36689,33 +37185,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *op1; - - op1 = EX_VAR(opline->op1.var); - if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { - ZVAL_LONG(EX_VAR(opline->result.var), ~Z_LVAL_P(op1)); - ZEND_VM_NEXT_OPCODE(); - } - - SAVE_OPLINE(); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - op1 = ZVAL_UNDEFINED_OP1(); - } - bitwise_not_function(EX_VAR(opline->result.var), op1); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; - val = EX_VAR(opline->op1.var); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -36740,18 +37214,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -36780,7 +37246,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36799,7 +37264,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36818,18 +37282,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RE static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -36859,7 +37315,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36878,7 +37333,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36897,16 +37351,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RE static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -36934,7 +37382,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -36951,16 +37398,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_H static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); - } - SAVE_OPLINE(); if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { ZVAL_NULL(var_ptr); @@ -36988,7 +37429,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); @@ -37005,7 +37445,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_H static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *z; SAVE_OPLINE(); @@ -37034,8 +37473,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCO static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = EX_VAR(opline->op1.var); @@ -37053,20 +37492,23 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDL } SAVE_OPLINE(); + op1_type = IS_CV; if (i_zend_is_true(val)) { opline++; } else { opline = OP_JMP_ADDR(opline, opline->op2); } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = EX_VAR(opline->op1.var); @@ -37084,20 +37526,23 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HAND } SAVE_OPLINE(); + op1_type = IS_CV; if (i_zend_is_true(val)) { opline = OP_JMP_ADDR(opline, opline->op2); } else { opline++; } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; + zend_uchar op1_type; val = EX_VAR(opline->op1.var); @@ -37116,21 +37561,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OP } SAVE_OPLINE(); + op1_type = IS_CV; if (i_zend_is_true(val)) { opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); } else { opline = OP_JMP_ADDR(opline, opline->op2); } - + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } ZEND_VM_JMP(opline); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; - int ret; + bool ret; val = EX_VAR(opline->op1.var); @@ -37165,9 +37612,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *val; - int ret; + bool ret; val = EX_VAR(opline->op1.var); @@ -37203,10 +37649,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = EX_VAR(opline->op1.var); return_value = EX(return_value); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -37215,9 +37661,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN } } else if (!return_value) { if (IS_CV & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -37232,7 +37678,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { @@ -37268,6 +37714,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN } } } + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -37275,10 +37724,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( { USE_OPLINE zval *retval_ptr; - + zval *return_value; SAVE_OPLINE(); + return_value = EX(return_value); + do { if ((IS_CV & (IS_CONST|IS_TMP_VAR)) || (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -37286,15 +37737,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( zend_error(E_NOTICE, "Only variable references should be returned by reference"); retval_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - if (!EX(return_value)) { + if (!return_value) { } else { if (IS_CV == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); break; } - ZVAL_NEW_REF(EX(return_value), retval_ptr); + ZVAL_NEW_REF(return_value, retval_ptr); if (IS_CV == IS_CONST) { Z_TRY_ADDREF_P(retval_ptr); } @@ -37308,8 +37759,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); - if (EX(return_value)) { - ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); } else { } @@ -37317,17 +37768,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( } } - if (EX(return_value)) { + if (return_value) { if (Z_ISREF_P(retval_ptr)) { Z_ADDREF_P(retval_ptr); } else { ZVAL_MAKE_REF_EX(retval_ptr, 2); } - ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } } while (0); + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -37336,7 +37788,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CV_HANDL USE_OPLINE zval *retval; - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); SAVE_OPLINE(); @@ -37380,7 +37831,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC USE_OPLINE zval *value; - SAVE_OPLINE(); value = EX_VAR(opline->op1.var); @@ -37405,187 +37855,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC } while (0); zend_exception_save(); - if (IS_CV != IS_TMP_VAR) { - Z_TRY_ADDREF_P(value); - } - + Z_TRY_ADDREF_P(value); zend_throw_exception_object(value); zend_exception_restore(); HANDLE_EXCEPTION(); } -static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - - - varptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - 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_CV == IS_CV) { - ZVAL_COPY_DEREF(arg, varptr); - } else /* if (IS_CV == 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_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - ZEND_VM_TAIL_CALL(ZEND_SEND_VAR_SPEC_CV_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *varptr, *arg; - - SAVE_OPLINE(); - varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); - - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(varptr))) { - ZVAL_NEW_EMPTY_REF(arg); - ZVAL_NULL(Z_REFVAL_P(arg)); - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_ISREF_P(varptr)) { - Z_ADDREF_P(varptr); - } else { - ZVAL_MAKE_REF_EX(varptr, 2); - } - ZVAL_REF(arg, Z_REF_P(varptr)); - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(0)) { - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var_by_ref; - } - } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_var_by_ref: - ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - varptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - 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_CV == IS_CV) { - ZVAL_COPY_DEREF(arg, varptr); - } else /* if (IS_CV == 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - - uint32_t arg_num = opline->op2.num; - - if (EXPECTED(1)) { - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - goto send_var_by_ref; - } - } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_var_by_ref: - ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - varptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { - SAVE_OPLINE(); - ZVAL_UNDEFINED_OP1(); - 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_CV == IS_CV) { - ZVAL_COPY_DEREF(arg, varptr); - } else /* if (IS_CV == 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_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *arg, *param; - SAVE_OPLINE(); if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { @@ -37604,7 +37885,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCO USE_OPLINE zval *val; - val = EX_VAR(opline->op1.var); if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); @@ -37629,8 +37909,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCO static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -37638,10 +37918,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC SAVE_OPLINE(); obj = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - do { if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { @@ -37664,9 +37940,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -37687,7 +37964,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -37695,7 +37972,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zval *result = EX_VAR(opline->result.var); HashTable *ht; @@ -37704,12 +37980,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO expr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); switch (opline->extended_value) { - case IS_NULL: - ZVAL_NULL(result); - break; - case _IS_BOOL: - ZVAL_BOOL(result, zend_is_true(expr)); - break; case IS_LONG: ZVAL_LONG(result, zval_get_long(expr)); break; @@ -37720,6 +37990,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO ZVAL_STR(result, zval_get_string(expr)); break; default: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); if (IS_CV & (IS_VAR|IS_CV)) { ZVAL_DEREF(expr); } @@ -37762,6 +38033,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO } } } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def)); if (Z_TYPE_P(expr) == IS_ARRAY) { ht = zend_symtable_to_proptable(Z_ARR_P(expr)); @@ -37789,14 +38061,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE { USE_OPLINE zend_op_array *new_op_array; - zval *inc_filename; SAVE_OPLINE(); inc_filename = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); - if (UNEXPECTED(EG(exception) != NULL)) { + if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { destroy_op_array(new_op_array); efree_size(new_op_array, sizeof(zend_op_array)); @@ -37830,7 +38101,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE call->prev_execute_data = execute_data; i_init_code_execute_data(call, new_op_array, return_value); + if (EXPECTED(zend_execute_ex == execute_ex)) { + ZEND_VM_ENTER(); } else { ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); @@ -37842,19 +38115,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE efree_size(new_op_array, sizeof(zend_op_array)); if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); + UNDEF_RESULT(); HANDLE_EXCEPTION(); } } else if (RETURN_VALUE_USED(opline)) { ZVAL_FALSE(EX_VAR(opline->result.var)); } + ZEND_VM_NEXT_OPCODE(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *result; SAVE_OPLINE(); @@ -37870,17 +38144,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (IS_CV != IS_TMP_VAR) { @@ -37908,7 +38185,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; @@ -37919,7 +38196,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array_ptr, *array_ref; SAVE_OPLINE(); @@ -38006,7 +38282,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; if (IS_CV == IS_VAR) { @@ -38021,10 +38297,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *ref = NULL; - int ret; + bool ret; SAVE_OPLINE(); value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -38070,7 +38345,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *ref = NULL; @@ -38109,7 +38383,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *result = EX_VAR(opline->result.var); @@ -38148,14 +38421,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - zval *val; - SAVE_OPLINE(); - val = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + val = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); @@ -38164,9 +38434,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN HANDLE_EXCEPTION(); } +yield_from_try_again: if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); - if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { + if (Z_OPT_REFCOUNTED_P(val)) { Z_ADDREF_P(val); } Z_FE_POS(generator->values) = 0; @@ -38176,11 +38447,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN if (ce == zend_ce_generator) { zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - if (IS_CV != IS_TMP_VAR) { - Z_ADDREF_P(val); - } + Z_ADDREF_P(val); - if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); zval_ptr_dtor(val); @@ -38189,11 +38463,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN } else { zend_generator_yield_from(generator, new_gen); } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); } else { if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); @@ -38223,6 +38492,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN ZVAL_OBJ(&generator->values, &iter->std); } + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; } else { zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); @@ -38255,7 +38527,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP USE_OPLINE zval *value; - value = EX_VAR(opline->op1.var); if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); @@ -38292,9 +38563,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP zval_ptr_dtor(&tmp); } if (!EG(exception)) { - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + zend_type_error("strlen(): Argument #1 ($str) must be of type string, %s given", zend_zval_type_name(value)); } - ZVAL_NULL(EX_VAR(opline->result.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } @@ -38307,11 +38578,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV zval *value; int result = 0; - value = EX_VAR(opline->op1.var); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -38333,15 +38603,73 @@ type_check_resource: SAVE_OPLINE(); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + uint32_t fetch_type; + zend_class_entry *called_scope, *scope; + USE_OPLINE + + if (IS_CV != IS_UNUSED) { + zval *op = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_OBJECT) { + zend_type_error("Cannot use \"::class\" on value of type %s", zend_zval_type_name(op)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + HANDLE_EXCEPTION(); + } + } + + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + fetch_type = opline->op1.num; + scope = EX(func)->op_array.scope; + if (UNEXPECTED(scope == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot use \"%s\" in the global scope", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name); + break; + case ZEND_FETCH_CLASS_PARENT: + if (UNEXPECTED(scope->parent == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, + "Cannot use \"parent\" when current class scope has no parent"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name); + break; + case ZEND_FETCH_CLASS_STATIC: + if (Z_TYPE(EX(This)) == IS_OBJECT) { + called_scope = Z_OBJCE(EX(This)); + } else { + called_scope = Z_CE(EX(This)); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38495,30 +38823,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SP USE_OPLINE zval *varptr, *arg; - - varptr = EX_VAR(opline->op1.var); - arg = ZEND_CALL_VAR(EX(call), opline->result.var); - - if (IS_CV == IS_CV) { - ZVAL_COPY(arg, varptr); - } else /* if (IS_CV == IS_VAR) */ { - ZVAL_COPY_VALUE(arg, varptr); - } - - ZEND_VM_NEXT_OPCODE(); -} - -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *varptr, *arg; - - uint32_t arg_num = opline->op2.num; - - if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - varptr = EX_VAR(opline->op1.var); arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -38534,7 +38838,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -38549,7 +38852,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -38564,7 +38866,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -38636,7 +38937,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -38647,14 +38947,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -38665,14 +38962,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38684,14 +38978,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38715,7 +39005,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -38735,7 +39025,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38748,13 +39037,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HA if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38778,7 +39063,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -38798,7 +39083,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38811,13 +39095,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_H if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38841,7 +39121,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -38861,7 +39141,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38873,14 +39152,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38904,7 +39179,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -38924,7 +39199,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -38937,13 +39211,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMP if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -38967,7 +39237,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -38987,7 +39257,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -39000,13 +39269,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMP if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -39030,7 +39295,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -39050,7 +39315,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -39065,7 +39329,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -39080,25 +39343,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -39109,16 +39368,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -39155,11 +39422,14 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_obj has two opcodes! */ @@ -39170,7 +39440,6 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -39199,7 +39468,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -39216,7 +39485,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -39241,7 +39510,7 @@ assign_dim_op_new_array: } else { zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); assign_dim_op_ret_null: - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -39255,7 +39524,6 @@ assign_dim_op_ret_null: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; zval *value; @@ -39263,26 +39531,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLE value = RT_CONSTANT(opline, opline->op2); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -39292,20 +39554,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { @@ -39318,16 +39576,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HAND && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -39341,7 +39607,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -39352,20 +39621,16 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); do { @@ -39378,16 +39643,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HAN && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -39400,7 +39673,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -39411,7 +39687,6 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; SAVE_OPLINE(); @@ -39447,7 +39722,6 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -39455,8 +39729,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HAND zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39464,7 +39737,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -39472,8 +39744,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HAN zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39481,7 +39752,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -39514,7 +39784,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -39522,8 +39791,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_ zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39531,19 +39799,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CV == IS_CONST || @@ -39561,7 +39822,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -39570,9 +39831,11 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -39597,10 +39860,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -39611,7 +39874,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -39623,11 +39886,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -39651,16 +39925,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -39669,7 +39938,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HAND BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39677,21 +39946,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39699,19 +39963,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CV == IS_CONST || @@ -39731,9 +39988,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -39758,10 +40017,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -39772,7 +40031,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -39784,9 +40043,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -39822,22 +40091,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39845,16 +40108,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -39863,16 +40122,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -39962,11 +40220,26 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: @@ -39980,34 +40253,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -40097,13 +40365,28 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: @@ -40115,34 +40398,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -40232,13 +40510,28 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: @@ -40250,16 +40543,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -40268,16 +40557,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -40367,11 +40655,26 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: @@ -40385,9 +40688,7 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -40397,9 +40698,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = RT_CONSTANT((opline+1), (opline+1)->op1); SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); } @@ -40412,11 +40713,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -40433,6 +40735,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = RT_CONSTANT((opline+1), (opline+1)->op1); value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -40477,9 +40780,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: @@ -40499,9 +40800,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -40511,9 +40810,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -40526,6 +40825,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -40547,6 +40847,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -40561,14 +40862,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -40576,9 +40877,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -40592,9 +40893,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -40614,9 +40913,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -40626,9 +40923,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -40641,6 +40938,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -40662,6 +40960,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -40676,14 +40975,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -40691,9 +40990,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -40707,9 +41006,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -40729,9 +41026,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -40741,9 +41036,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); } @@ -40756,11 +41051,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -40777,6 +41073,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -40821,9 +41118,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: @@ -40843,7 +41138,6 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *variable_ptr; @@ -40851,27 +41145,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UN value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *variable_ptr; @@ -40879,40 +41165,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_US value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_CV == IS_UNUSED) { @@ -40933,7 +41206,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_O } - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -40941,17 +41214,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = RT_CONSTANT(opline, opline->op2); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -40983,7 +41250,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -41105,7 +41371,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -41117,10 +41382,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S object = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CONST != IS_CONST) { function_name = RT_CONSTANT(opline, opline->op2); } @@ -41147,12 +41408,26 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } while (0); } - if (IS_CV != IS_UNUSED) { + if (IS_CV == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CV & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -41176,7 +41451,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if (IS_CONST == IS_CONST && @@ -41196,18 +41470,21 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -41220,9 +41497,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -41230,9 +41509,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -41246,10 +41522,150 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == 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_REF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + 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)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == 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_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -41288,7 +41704,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS } if (IS_CONST != IS_UNUSED) { - zval *offset = RT_CONSTANT(opline, opline->op2); zend_string *str; zend_ulong hval; @@ -41368,7 +41783,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; zend_ulong hval; @@ -41426,7 +41840,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -41445,7 +41859,7 @@ num_index_dim: if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -41458,15 +41872,12 @@ num_index_dim: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } offset = RT_CONSTANT(opline, opline->op2); do { @@ -41484,7 +41895,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -41494,9 +41916,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; + bool result; zend_ulong hval; zval *offset; @@ -41544,8 +41965,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -41571,25 +41990,18 @@ isset_dim_obj_exit: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = RT_CONSTANT(opline, opline->op2); if (IS_CV == IS_CONST || @@ -41606,26 +42018,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -41643,20 +42066,18 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zend_bool result; @@ -41678,7 +42099,6 @@ try_instanceof: } else if (IS_CONST == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -41698,8 +42118,6 @@ try_instanceof: } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -41721,8 +42139,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE /* Set the new yielded value */ if (IS_CV != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -41790,26 +42206,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { - zval *key = RT_CONSTANT(opline, opline->op2); - - /* Consts, temporary variables and references need copying */ - if (IS_CONST == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CONST == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CONST == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -41845,7 +42246,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_string *varname; zval *value; zval *variable_ptr; @@ -41903,23 +42303,22 @@ check_indirect: variable_ptr = EX_VAR(opline->op1.var); if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(variable_ptr); - uint32_t refcnt = GC_DELREF(ref); + zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); - if (EXPECTED(variable_ptr != value)) { - if (refcnt == 0) { - SAVE_OPLINE(); - rc_dtor_func(ref); - if (UNEXPECTED(EG(exception))) { - ZVAL_NULL(variable_ptr); - HANDLE_EXCEPTION(); - } - } else { - gc_check_possible_root(ref); + ZVAL_REF(variable_ptr, ref); + if (GC_DELREF(garbage) == 0) { + SAVE_OPLINE(); + rc_dtor_func(garbage); + if (UNEXPECTED(EG(exception))) { + ZVAL_NULL(variable_ptr); + HANDLE_EXCEPTION(); } + } else { + gc_check_possible_root(garbage); } + } else { + ZVAL_REF(variable_ptr, ref); } - ZVAL_REF(variable_ptr, ref); ZEND_VM_REPEAT_OPCODE(ZEND_BIND_GLOBAL); ZEND_VM_NEXT_OPCODE(); @@ -41928,7 +42327,6 @@ check_indirect: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); zval *result; @@ -41947,13 +42345,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1); } else { zend_string *key; - zval key_tmp, result_tmp, *val; + zval key_tmp, *val; result = NULL; ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { ZVAL_STR(&key_tmp, key); - compare_function(&result_tmp, op1, &key_tmp); - if (Z_LVAL(result_tmp) == 0) { + if (zend_compare(op1, &key_tmp) == 0) { result = val; break; } @@ -41961,14 +42358,40 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */ + /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */ + /* (Infinite recursion when comparing arrays is an uncatchable fatal error) */ USE_OPLINE + zval *op1, *op2; + zend_bool result; + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(!result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE zval *container, *dim, *value; zend_long offset; HashTable *ht; @@ -42021,7 +42444,6 @@ fetch_dim_r_index_undef: static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; zend_long offset; HashTable *ht; @@ -42074,41 +42496,38 @@ fetch_dim_r_index_undef: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); fast_div_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { @@ -42168,7 +42587,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( } concat_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } @@ -42176,26 +42595,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42219,7 +42633,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -42239,12 +42653,11 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -42252,13 +42665,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_H if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42282,7 +42691,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -42302,12 +42711,11 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -42315,13 +42723,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_ if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42345,7 +42749,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -42365,26 +42769,21 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42408,7 +42807,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -42428,12 +42827,11 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -42441,13 +42839,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JM if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42471,7 +42865,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -42491,12 +42885,11 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; double d1, d2; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { /* pass */ } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -42504,13 +42897,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JM if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -42534,7 +42923,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -42554,55 +42943,49 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); boolean_xor_function(EX_VAR(opline->result.var), op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -42613,16 +42996,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_H && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -42659,12 +43050,15 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); - zval_ptr_dtor_nogc(free_op2); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -42674,7 +43068,6 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -42685,7 +43078,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H assign_dim_op_array: SEPARATE_ARRAY(container); assign_dim_op_new_array: - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { @@ -42703,7 +43096,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -42720,7 +43113,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -42729,7 +43122,7 @@ assign_dim_op_new_array: } } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -42745,14 +43138,14 @@ assign_dim_op_new_array: } else { zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); assign_dim_op_ret_null: - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -42760,37 +43153,30 @@ assign_dim_op_ret_null: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *var_ptr; zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42798,21 +43184,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -42824,16 +43206,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HAN && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -42847,11 +43237,14 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42859,21 +43252,17 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -42885,16 +43274,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HA && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -42907,11 +43304,14 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42919,12 +43319,11 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container, *dim, *value; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV != IS_CONST) { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { fetch_dim_r_array: @@ -42947,7 +43346,7 @@ fetch_dim_r_slow: } else { zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42955,16 +43354,14 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42972,16 +43369,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42989,13 +43384,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43022,16 +43416,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43039,20 +43431,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -43069,7 +43454,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -43078,9 +43463,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -43105,10 +43492,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -43119,7 +43506,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -43131,11 +43518,22 @@ fetch_obj_r_fast_copy: } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -43146,7 +43544,7 @@ fetch_obj_r_copy: } while (0); fetch_obj_r_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43154,25 +43552,20 @@ fetch_obj_r_finish: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43180,21 +43573,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43202,20 +43590,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op2; zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -43234,9 +43615,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -43261,10 +43644,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -43275,7 +43658,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -43287,9 +43670,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -43300,7 +43693,7 @@ fetch_obj_is_copy: } while (0); fetch_obj_is_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43325,22 +43718,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2; zval *container, *property, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -43348,17 +43735,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -43366,16 +43749,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -43465,15 +43847,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -43483,34 +43880,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -43600,15 +43992,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -43618,34 +44025,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -43735,15 +44137,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -43753,17 +44170,13 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { @@ -43771,16 +44184,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -43870,15 +44282,30 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); @@ -43888,9 +44315,7 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -43900,9 +44325,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = RT_CONSTANT((opline+1), (opline+1)->op1); SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); } @@ -43915,11 +44340,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -43927,7 +44353,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -43936,6 +44362,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = RT_CONSTANT((opline+1), (opline+1)->op1); value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -43949,7 +44376,7 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -43963,7 +44390,7 @@ try_assign_dim_array: UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -43972,7 +44399,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -43980,10 +44407,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -43992,7 +44417,7 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } /* assign_dim has two opcodes! */ @@ -44002,9 +44427,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -44014,9 +44437,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -44029,6 +44452,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -44041,7 +44465,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -44050,6 +44474,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -44063,31 +44488,31 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -44095,10 +44520,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -44107,7 +44530,7 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } /* assign_dim has two opcodes! */ @@ -44117,9 +44540,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -44129,9 +44550,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -44144,6 +44565,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -44156,7 +44578,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -44165,6 +44587,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -44178,31 +44601,31 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { @@ -44210,10 +44633,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -44222,7 +44643,7 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } /* assign_dim has two opcodes! */ @@ -44232,9 +44653,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -44244,9 +44663,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); } @@ -44259,11 +44678,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -44271,7 +44691,7 @@ try_assign_dim_array: } } } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); } else { @@ -44280,6 +44700,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -44293,7 +44714,7 @@ try_assign_dim_array: } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { @@ -44307,7 +44728,7 @@ try_assign_dim_array: UNDEF_RESULT(); } else { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); @@ -44316,7 +44737,7 @@ try_assign_dim_array: if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); UNDEF_RESULT(); } else { @@ -44324,10 +44745,8 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } - dim = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -44336,7 +44755,7 @@ assign_dim_error: } } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } /* assign_dim has two opcodes! */ @@ -44346,20 +44765,14 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_CV == IS_UNUSED) { @@ -44379,8 +44792,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ zend_assign_to_property_reference(container, IS_CV, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -44388,18 +44801,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - property = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -44421,7 +44828,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ zend_assign_to_property_reference(container, IS_CV, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -44430,13 +44837,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; zend_string *op1_str, *op2_str, *str; op1 = EX_VAR(opline->op1.var); - op2 = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { zend_string *op1_str = Z_STR_P(op1); @@ -44544,7 +44950,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -44552,7 +44958,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA { USE_OPLINE zval *function_name; - zend_free_op free_op1, free_op2; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -44564,12 +44969,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA object = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST && @@ -44588,18 +44989,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } } zend_throw_error(NULL, "Method name must be a string"); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } while (0); } - if (IS_CV != IS_UNUSED) { + if (IS_CV == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CV & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -44607,23 +45022,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA object = ZVAL_UNDEFINED_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } HANDLE_EXCEPTION(); } } if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } zend_invalid_method_call(object, function_name); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); } } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if ((IS_TMP_VAR|IS_VAR) == IS_CONST && @@ -44633,7 +45047,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA zend_object *orig_obj = obj; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); } /* First, locate the function. */ @@ -44642,19 +45056,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA if (EXPECTED(!EG(exception))) { zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - zval_ptr_dtor_nogc(free_op2); - + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -44662,14 +45079,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -44677,9 +45096,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -44696,7 +45112,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -44735,8 +45150,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV } if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { - zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); zend_string *str; zend_ulong hval; @@ -44781,7 +45195,7 @@ num_index: zend_illegal_offset(); zval_ptr_dtor_nogc(expr_ptr); } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -44815,7 +45229,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; zval *offset; zend_ulong hval; @@ -44823,7 +45236,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDL SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -44873,7 +45286,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -44892,13 +45305,13 @@ num_index_dim: if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -44906,16 +45319,13 @@ num_index_dim: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { @@ -44932,10 +45342,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -44943,15 +45364,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; - int result; + bool result; zend_ulong hval; zval *offset; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht; @@ -44991,10 +45411,8 @@ num_index_prop: if (IS_CV & (IS_CONST|IS_CV)) { /* avoid exception check */ - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -45017,29 +45435,22 @@ num_index_prop: } isset_dim_obj_exit: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - offset = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { @@ -45055,31 +45466,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); key = EX_VAR(opline->op1.var); - subject = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { array_key_exists_array: @@ -45092,110 +45514,17 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_identical_function(op1, op2); - - zval_ptr_dtor_nogc(free_op2); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *op1, *op2; - zend_bool result; - - SAVE_OPLINE(); - op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - result = fast_is_not_identical_function(op1, op2); - - zval_ptr_dtor_nogc(free_op2); - ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = EX_VAR(opline->op1.var); - - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op2; - zval *value; - zval *variable_ptr; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - variable_ptr = EX_VAR(opline->op1.var); - - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -45214,8 +45543,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND /* Set the new yielded value */ if (IS_CV != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -45282,27 +45609,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND } /* Set the new yielded key */ - if (IS_TMP_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_tmp(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_TMP_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_TMP_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -45335,118 +45648,161 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); result = fast_is_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *op1, *op2; zend_bool result; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - op2 = _get_zval_ptr_var_deref(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); result = fast_is_not_identical_function(op1, op2); - zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *value; zval *variable_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2; zval *variable_ptr; zval *value_ptr; SAVE_OPLINE(); - value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (IS_CV == IS_VAR && + if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -45462,7 +45818,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } - if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45470,7 +45826,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zend_bool result; @@ -45492,7 +45847,6 @@ try_instanceof: } else if (IS_VAR == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -45512,154 +45866,11 @@ try_instanceof: } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_CV != IS_UNUSED) { - - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CV & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_CV == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - - } - } else { - zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->value, value); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - - } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } - } - } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); - } - - /* Set the new yielded key */ - if (IS_VAR != IS_UNUSED) { - zend_free_op free_op2; - zval *key = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_VAR == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_VAR == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - zval_ptr_dtor_nogc(free_op2); - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } - } - - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; - } - - /* We increment to the next op, so we are at the correct position when the - * generator is resumed. */ - ZEND_VM_INC_OPCODE(); - - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -45688,7 +45899,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -45705,7 +45916,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -45730,7 +45941,7 @@ assign_dim_op_new_array: } else { zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); assign_dim_op_ret_null: - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -45744,7 +45955,6 @@ assign_dim_op_ret_null: static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE - zval *varname; zval *retval; zend_string *name, *tmp_name; @@ -45786,7 +45996,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { @@ -45805,7 +46015,7 @@ fetch_this: } else if (type == BP_VAR_IS) { retval = &EG(uninitialized_zval); } else { - zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name)); + zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(name)); if (type == BP_VAR_RW) { ZVAL_NULL(retval); } else { @@ -45869,7 +46079,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -45877,8 +46086,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HAN zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45886,7 +46094,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -45894,8 +46101,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HA zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45922,9 +46128,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -45934,9 +46138,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = RT_CONSTANT((opline+1), (opline+1)->op1); SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); } @@ -45949,11 +46153,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -45970,6 +46175,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = RT_CONSTANT((opline+1), (opline+1)->op1); value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -46014,9 +46220,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: @@ -46036,9 +46240,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -46048,9 +46250,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -46063,6 +46265,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -46084,6 +46287,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -46098,14 +46302,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -46113,9 +46317,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -46129,9 +46333,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -46151,9 +46353,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -46163,9 +46363,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -46178,6 +46378,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -46199,6 +46400,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -46213,14 +46415,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -46228,9 +46430,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -46244,9 +46446,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -46266,9 +46466,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -46278,9 +46476,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); } @@ -46293,11 +46491,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -46314,6 +46513,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -46358,9 +46558,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = NULL; assign_dim_error: @@ -46379,58 +46577,281 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE - - SAVE_OPLINE(); if (IS_CV == IS_UNUSED) { - zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num)); + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); } else { /* prevents "undefined variable opline" errors */ #if 0 || (IS_CV != IS_UNUSED) + USE_OPLINE zval *retval_ref, *retval_ptr; - zend_arg_info *ret_info = EX(func)->common.arg_info - 1; - - retval_ref = retval_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + retval_ref = retval_ptr = EX_VAR(opline->op1.var); if (IS_CV == IS_CONST) { ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); retval_ref = retval_ptr = EX_VAR(opline->result.var); } else if (IS_CV == IS_VAR) { if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { - retval_ptr = Z_INDIRECT_P(retval_ptr); + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); } ZVAL_DEREF(retval_ptr); } else if (IS_CV == IS_CV) { ZVAL_DEREF(retval_ptr); } - if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && ZEND_TYPE_CODE(ret_info->type) != IS_CALLABLE - && ZEND_TYPE_CODE(ret_info->type) != IS_ITERABLE - && !ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(ret_info->type), Z_TYPE_P(retval_ptr)) - && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) - && retval_ref != retval_ptr) - ) { - /* A cast might happen - unwrap the reference if this is a by-value return */ - if (Z_REFCOUNT_P(retval_ref) == 1) { - ZVAL_UNREF(retval_ref); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + void *cache_slot = CACHE_ADDR(opline->op2.num); + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); } else { - Z_DELREF_P(retval_ref); - ZVAL_COPY(retval_ref, retval_ptr); + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; } - retval_ptr = retval_ref; } - zend_verify_return_type(EX(func), retval_ptr, CACHE_ADDR(opline->op2.num)); + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); #endif } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == 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_REF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + SAVE_OPLINE(); + if (IS_UNUSED == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + ZEND_VM_NEXT_OPCODE(); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == 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_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + ZEND_VM_NEXT_OPCODE(); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == 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_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -46469,7 +46890,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS } if (IS_UNUSED != IS_UNUSED) { - zval *offset = NULL; zend_string *str; zend_ulong hval; @@ -46575,7 +46995,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL zend_string *name, *tmp_name; HashTable *target_symbol_table; - SAVE_OPLINE(); varname = EX_VAR(opline->op1.var); @@ -46617,25 +47036,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_CV_S if (Z_TYPE_P(value) > IS_NULL && (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else { - int result; + bool result; SAVE_OPLINE(); result = !i_zend_is_true(value); - if (UNEXPECTED(EG(exception))) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH(result, 1); } } @@ -46649,25 +47058,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_CV_S if (Z_TYPE_P(value) > IS_NULL && (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { ZEND_VM_SMART_BRANCH_TRUE(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { ZEND_VM_SMART_BRANCH_FALSE(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else { - int result; + bool result; SAVE_OPLINE(); result = !i_zend_is_true(value); - if (UNEXPECTED(EG(exception))) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH(result, 1); } } @@ -46675,8 +47074,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS { USE_OPLINE zval *value; + /* Should be bool result? as below got: result = (opline->extended_value & ZEND_ISEMPTY) */ int result; - zval *varname; zend_string *name, *tmp_name; HashTable *target_symbol_table; @@ -46713,15 +47112,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; zend_bool result; @@ -46743,7 +47139,6 @@ try_instanceof: } else if (IS_UNUSED == IS_UNUSED) { ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { - ZEND_ASSERT(EG(exception)); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -46763,8 +47158,6 @@ try_instanceof: } ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -46786,8 +47179,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z /* Set the new yielded value */ if (IS_CV != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -46855,26 +47246,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { - zval *key = NULL; - - /* Consts, temporary variables and references need copying */ - if (IS_UNUSED == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_UNUSED == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_UNUSED == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -46910,13 +47286,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - HashTable *ht; zval *value; zval *variable_ptr; variable_ptr = EX_VAR(opline->op1.var); - i_zval_ptr_dtor(variable_ptr); ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr); if (!ht) { @@ -46937,14 +47311,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN if (Z_TYPE_P(value) == IS_CONSTANT_AST) { SAVE_OPLINE(); if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { - ZVAL_NULL(variable_ptr); HANDLE_EXCEPTION(); } } + + i_zval_ptr_dtor(variable_ptr); if (UNEXPECTED(!Z_ISREF_P(value))) { zend_reference *ref = (zend_reference*)emalloc(sizeof(zend_reference)); GC_SET_REFCOUNT(ref, 2); - GC_TYPE_INFO(ref) = IS_REFERENCE; + GC_TYPE_INFO(ref) = GC_REFERENCE; ZVAL_COPY_VALUE(&ref->val, value); ref->sources.ptr = NULL; Z_REF_P(value) = ref; @@ -46955,6 +47330,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN ZVAL_REF(variable_ptr, Z_REF_P(value)); } } else { + i_zval_ptr_dtor(variable_ptr); ZVAL_COPY(variable_ptr, value); } @@ -47010,20 +47386,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; zend_long count; SAVE_OPLINE(); op1 = EX_VAR(opline->op1.var); + while (1) { if (Z_TYPE_P(op1) == IS_ARRAY) { count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } if (UNEXPECTED(EG(exception))) { @@ -47033,29 +47411,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; } - /* If There's no handler and it doesn't implement Countable then add a warning */ - count = 1; + /* If There's no handler and it doesn't implement Countable then emit a TypeError */ } else if ((IS_CV & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { op1 = Z_REFVAL_P(op1); continue; - } else if (Z_TYPE_P(op1) <= IS_NULL) { - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP1(); - } - count = 0; - } else { - count = 1; + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count"); + count = 0; + zend_type_error("%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1)); break; } @@ -47071,15 +47444,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDL if (IS_CV == IS_UNUSED) { if (UNEXPECTED(!EX(func)->common.scope)) { SAVE_OPLINE(); - zend_error(E_WARNING, "get_class() called without object from outside a class"); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } else { ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); ZEND_VM_NEXT_OPCODE(); } } else { - zval *op1; SAVE_OPLINE(); @@ -47094,8 +47466,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDL if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1))); - ZVAL_FALSE(EX_VAR(opline->result.var)); + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_type_name(op1)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } break; } @@ -47107,13 +47479,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDL static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1; zend_string *type; SAVE_OPLINE(); op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - type = zend_zval_get_type(op1); + type = zend_zval_get_legacy_type(op1); if (EXPECTED(type)) { ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); } else { @@ -47123,10 +47494,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = EX_VAR(opline->op1.var); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_CV == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE zval *op1, *op2; SAVE_OPLINE(); @@ -47141,7 +47533,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -47156,7 +47547,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OP static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; op1 = EX_VAR(opline->op1.var); @@ -47228,7 +47618,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -47239,14 +47628,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_bool result; @@ -47257,14 +47643,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47276,14 +47659,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47307,7 +47686,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -47327,7 +47706,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47340,13 +47718,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDL if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47370,7 +47744,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -47390,7 +47764,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47403,13 +47776,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HAND if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { is_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47433,7 +47802,7 @@ is_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -47453,7 +47822,6 @@ is_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47465,14 +47833,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: - - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_TRUE_NONE(); } else { is_not_equal_false: - - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); + ZEND_VM_SMART_BRANCH_FALSE_NONE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47496,7 +47860,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -47516,7 +47880,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47529,13 +47892,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_H if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47559,7 +47918,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -47579,7 +47938,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; double d1, d2; @@ -47592,13 +47950,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_ if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { is_not_equal_true: ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); - ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } else { is_not_equal_false: ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); - ZVAL_FALSE(EX_VAR(opline->result.var)); - ZEND_VM_NEXT_OPCODE(); } } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { d1 = (double)Z_LVAL_P(op1); @@ -47622,7 +47976,7 @@ is_not_equal_double: } } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { - int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_str(op1); } @@ -47642,7 +47996,6 @@ is_not_equal_double: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -47657,7 +48010,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; SAVE_OPLINE(); @@ -47672,25 +48024,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object; zval *property; zval *value; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { @@ -47701,16 +48049,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDL && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -47747,11 +48103,14 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); - FREE_OP(free_op_data); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); /* assign_obj has two opcodes! */ @@ -47762,7 +48121,6 @@ assign_op_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data1; zval *var_ptr; zval *value, *container, *dim; @@ -47791,7 +48149,7 @@ assign_dim_op_new_array: } } - value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1); + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { @@ -47808,7 +48166,7 @@ assign_dim_op_new_array: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } - FREE_OP(free_op_data1); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { container = Z_REFVAL_P(container); @@ -47833,7 +48191,7 @@ assign_dim_op_new_array: } else { zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); assign_dim_op_ret_null: - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -47847,7 +48205,6 @@ assign_dim_op_ret_null: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *var_ptr; zval *value; @@ -47855,26 +48212,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(Z value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - do { - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { - zend_reference *ref = Z_REF_P(var_ptr); - var_ptr = Z_REFVAL_P(var_ptr); - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { - zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); - break; - } + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; } - zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); - } while (0); - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -47884,20 +48235,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -47910,16 +48257,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -47933,7 +48288,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -47944,20 +48302,16 @@ pre_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; zval *property; zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -47970,16 +48324,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLE && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - break; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; } post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -47992,7 +48354,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -48003,7 +48368,6 @@ post_incdec_object: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container, *dim, *value; SAVE_OPLINE(); @@ -48039,7 +48403,6 @@ fetch_dim_r_slow: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -48047,8 +48410,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -48056,7 +48418,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -48064,8 +48425,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLE zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -48073,7 +48433,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; SAVE_OPLINE(); @@ -48106,7 +48465,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container; SAVE_OPLINE(); @@ -48114,8 +48472,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HAN zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - zval *result = EX_VAR(opline->result.var); - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -48123,19 +48480,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST || @@ -48153,7 +48503,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_wrong_property_read(offset); + zend_wrong_property_read(container, offset); ZVAL_NULL(EX_VAR(opline->result.var)); goto fetch_obj_r_finish; } while (0); @@ -48162,9 +48512,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -48189,10 +48541,10 @@ fetch_obj_r_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_r_copy; @@ -48203,7 +48555,7 @@ fetch_obj_r_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -48215,11 +48567,22 @@ fetch_obj_r_fast_copy: } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -48238,16 +48601,11 @@ fetch_obj_r_finish: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address( @@ -48256,7 +48614,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -48264,21 +48622,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *property, *container, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -48286,19 +48639,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLE static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zval *offset; void **cache_slot = NULL; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || @@ -48318,9 +48664,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -48345,10 +48693,10 @@ fetch_obj_is_fast_copy: Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { goto fetch_obj_is_copy; @@ -48359,7 +48707,7 @@ fetch_obj_is_fast_copy: } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -48371,9 +48719,19 @@ fetch_obj_is_fast_copy: } } } + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -48409,22 +48767,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; zval *container, *property, *result; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); if (IS_CV == IS_VAR) { - FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result); + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -48432,16 +48784,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HAN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); @@ -48450,16 +48798,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -48549,11 +48896,26 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: @@ -48567,34 +48929,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -48684,13 +49041,28 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: @@ -48702,34 +49074,29 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -48819,13 +49186,28 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); exit_assign_obj: @@ -48837,16 +49219,12 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); @@ -48855,16 +49233,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ object = Z_REFVAL_P(object); goto assign_object; } - object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC); - if (UNEXPECTED(!object)) { - value = &EG(uninitialized_zval); - goto free_and_exit_assign_obj; - } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -48954,11 +49331,26 @@ fast_assign_obj: ZVAL_DEREF(value); } - value = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } free_and_exit_assign_obj: if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } exit_assign_obj: @@ -48972,9 +49364,7 @@ exit_assign_obj: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -48984,9 +49374,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = RT_CONSTANT((opline+1), (opline+1)->op1); SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { ZVAL_DEREF(value); } @@ -48999,11 +49389,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -49020,6 +49411,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = RT_CONSTANT((opline+1), (opline+1)->op1); value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -49064,9 +49456,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: @@ -49086,9 +49476,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -49098,9 +49486,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -49113,6 +49501,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -49134,6 +49523,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -49148,14 +49538,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -49163,9 +49553,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -49179,9 +49569,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -49201,9 +49589,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -49213,9 +49599,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { ZVAL_DEREF(value); } @@ -49228,6 +49614,7 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -49249,6 +49636,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -49263,14 +49651,14 @@ try_assign_dim_array: } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -49278,9 +49666,9 @@ try_assign_dim_array: UNDEF_RESULT(); } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); - zval_ptr_dtor_nogc(free_op_data); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -49294,9 +49682,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); @@ -49316,9 +49702,7 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object_ptr, *orig_object_ptr; - zend_free_op free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -49328,9 +49712,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { try_assign_dim_array: - value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); SEPARATE_ARRAY(object_ptr); if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_CV || IS_CV == IS_VAR) { ZVAL_DEREF(value); } @@ -49343,11 +49727,12 @@ try_assign_dim_array: Z_ADDREF_P(value); } } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); if (value != free_op_data) { if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); } - + zval_ptr_dtor_nogc(free_op_data); } } else if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_REFCOUNTED_P(value))) { @@ -49364,6 +49749,7 @@ try_assign_dim_array: if (UNEXPECTED(variable_ptr == NULL)) { goto assign_dim_error; } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -49408,9 +49794,7 @@ try_assign_dim_array: goto try_assign_dim_array; } } else { - if (IS_CV != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) { - zend_use_scalar_as_array(); - } + zend_use_scalar_as_array(); dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: @@ -49430,7 +49814,6 @@ assign_dim_error: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *variable_ptr; @@ -49438,27 +49821,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSE value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(0)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *value; zval *variable_ptr; @@ -49466,27 +49841,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_ value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - - if (UNEXPECTED(1)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } - - /* zend_assign_to_variable() always takes care of op2, never free it! */ + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *variable_ptr; zval *value_ptr; @@ -49494,15 +49861,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - variable_ptr = &EG(uninitialized_zval); - } else if (IS_CV == IS_VAR && + if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); variable_ptr = &EG(uninitialized_zval); - } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) { - variable_ptr = &EG(uninitialized_zval); } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { @@ -49525,20 +49888,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data; zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var, &free_op_data EXECUTE_DATA_CC); + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (1) { if (IS_CV == IS_UNUSED) { @@ -49559,7 +49916,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_D } - if (UNEXPECTED(free_op_data)) {zval_ptr_dtor_nogc(free_op_data);}; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));; ZEND_VM_NEXT_OPCODE_EX(1, 2); } @@ -49567,17 +49924,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_D static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *property, *container, *value_ptr; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); @@ -49609,7 +49960,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_D static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *op1, *op2; zend_string *op1_str, *op2_str, *str; @@ -49731,7 +50081,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA { USE_OPLINE zval *function_name; - zend_free_op free_op1; zval *object; zend_function *fbc; zend_class_entry *called_scope; @@ -49743,10 +50092,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA object = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - if (IS_CV != IS_CONST) { function_name = EX_VAR(opline->op2.var); } @@ -49773,12 +50118,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } while (0); } - if (IS_CV != IS_UNUSED) { + if (IS_CV == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { do { - if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { - object = Z_REFVAL_P(object); + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CV & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } break; } } @@ -49802,7 +50161,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } while (0); } - obj = Z_OBJ_P(object); called_scope = obj->ce; if (IS_CV == IS_CONST && @@ -49822,18 +50180,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA zend_undefined_method(obj->ce, Z_STR_P(function_name)); } - + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); } if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { - /* Reset "object" to trigger reference counting */ - object = NULL; + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -49846,9 +50207,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - - if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } /* call static method */ obj = (zend_object*)called_scope; @@ -49856,9 +50219,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ - } else if (free_op1 != object) { - GC_ADDREF(obj); /* For $this pointer */ - } /* CV may be changed indirectly (e.g. when it's a reference) */ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; @@ -49875,7 +50235,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr_ptr, new_expr; SAVE_OPLINE(); @@ -49914,7 +50273,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H } if (IS_CV != IS_UNUSED) { - zval *offset = EX_VAR(opline->op2.var); zend_string *str; zend_ulong hval; @@ -49994,7 +50352,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; zend_ulong hval; @@ -50052,7 +50409,7 @@ num_index_dim: key = ZSTR_EMPTY_ALLOC(); goto str_index_dim; } else { - zend_error(E_WARNING, "Illegal offset type in unset"); + zend_type_error("Illegal offset type in unset"); } break; } else if (Z_ISREF_P(container)) { @@ -50071,7 +50428,7 @@ num_index_dim: if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -50084,15 +50441,12 @@ num_index_dim: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); do { @@ -50110,7 +50464,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -50120,9 +50485,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - int result; + bool result; zend_ulong hval; zval *offset; @@ -50170,8 +50534,6 @@ num_index_prop: /* avoid exception check */ ZEND_VM_SMART_BRANCH(result, 0); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE(); } } else { result = (value == NULL || !i_zend_is_true(value)); @@ -50197,25 +50559,18 @@ isset_dim_obj_exit: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - - if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { - ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (IS_CV == IS_CONST || @@ -50232,26 +50587,37 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: ZEND_VM_SMART_BRANCH(result, 1); - ZVAL_BOOL(EX_VAR(opline->result.var), result); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *key, *subject; HashTable *ht; - uint32_t result; + zend_bool result; SAVE_OPLINE(); @@ -50269,13 +50635,12 @@ array_key_exists_array: goto array_key_exists_array; } } - result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC); + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; } - ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1); - Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + ZEND_VM_SMART_BRANCH(result, 1); } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ @@ -50298,8 +50663,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ /* Set the new yielded value */ if (IS_CV != IS_UNUSED) { - - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ @@ -50367,26 +50730,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->key, key); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { - Z_ADDREF(generator->key); - } - } else if (IS_CV == IS_TMP_VAR) { - ZVAL_COPY_VALUE(&generator->key, key); - } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { - ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); - - } else { - ZVAL_COPY_VALUE(&generator->key, key); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); - } + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + key = Z_REFVAL_P(key); } + ZVAL_COPY(&generator->key, key); if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key @@ -50419,10 +50767,40 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ ZEND_VM_RETURN(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */ + /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */ + /* (Infinite recursion when comparing arrays is an uncatchable fatal error) */ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(!result, 0); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type); ZEND_VM_NEXT_OPCODE(); /* Never reached */ } @@ -50448,15 +50826,34 @@ ZEND_API void execute_ex(zend_execute_data *ex) { DCL_OPLINE +#if defined(ZEND_VM_IP_GLOBAL_REG) || defined(ZEND_VM_IP_GLOBAL_REG) + struct { #ifdef ZEND_VM_IP_GLOBAL_REG - const zend_op *orig_opline = opline; + const zend_op *orig_opline; #endif #ifdef ZEND_VM_FP_GLOBAL_REG - zend_execute_data *orig_execute_data = execute_data; + zend_execute_data *orig_execute_data; +#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE + char hybrid_jit_red_zone[ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE]; +#endif +#endif + } vm_stack_data; +#endif +#ifdef ZEND_VM_IP_GLOBAL_REG + vm_stack_data.orig_opline = opline; +#endif +#ifdef ZEND_VM_FP_GLOBAL_REG + vm_stack_data.orig_execute_data = execute_data; execute_data = ex; #else zend_execute_data *execute_data = ex; #endif +#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE + memset(vm_stack_data.hybrid_jit_red_zone, 0, ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE); + if (zend_touch_vm_stack_data) { + zend_touch_vm_stack_data(&vm_stack_data); + } +#endif #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) if (UNEXPECTED(execute_data == NULL)) { @@ -50763,10 +51160,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_POW_SPEC_CV_CV_LABEL, (void*)&&ZEND_BW_NOT_SPEC_CONST_LABEL, - (void*)&&ZEND_BW_NOT_SPEC_TMPVAR_LABEL, - (void*)&&ZEND_BW_NOT_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_BW_NOT_SPEC_TMPVARCV_LABEL, + (void*)&&ZEND_BW_NOT_SPEC_TMPVARCV_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_BW_NOT_SPEC_CV_LABEL, + (void*)&&ZEND_BW_NOT_SPEC_TMPVARCV_LABEL, (void*)&&ZEND_BOOL_NOT_SPEC_CONST_LABEL, (void*)&&ZEND_BOOL_NOT_SPEC_TMPVAR_LABEL, (void*)&&ZEND_BOOL_NOT_SPEC_TMPVAR_LABEL, @@ -51748,8 +52145,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_CASE_SPEC_TMPVAR_CV_LABEL, (void*)&&ZEND_CHECK_VAR_SPEC_CV_UNUSED_LABEL, - (void*)&&ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_LABEL, - (void*)&&ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK_LABEL, + (void*)&&ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_LABEL, + (void*)&&ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_CAST_SPEC_CONST_LABEL, (void*)&&ZEND_CAST_SPEC_TMP_LABEL, (void*)&&ZEND_CAST_SPEC_VAR_LABEL, @@ -51805,34 +52210,121 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_LABEL, (void*)&&ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_LABEL, (void*)&&ZEND_DO_FCALL_SPEC_RETVAL_USED_LABEL, + (void*)&&ZEND_DO_FCALL_SPEC_OBSERVER_LABEL, + (void*)&&ZEND_DO_FCALL_SPEC_OBSERVER_LABEL, (void*)&&ZEND_INIT_FCALL_SPEC_CONST_LABEL, (void*)&&ZEND_RETURN_SPEC_CONST_LABEL, + (void*)&&ZEND_RETURN_SPEC_OBSERVER_LABEL, (void*)&&ZEND_RETURN_SPEC_TMP_LABEL, + (void*)&&ZEND_RETURN_SPEC_OBSERVER_LABEL, (void*)&&ZEND_RETURN_SPEC_VAR_LABEL, + (void*)&&ZEND_RETURN_SPEC_OBSERVER_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_RETURN_SPEC_CV_LABEL, + (void*)&&ZEND_RETURN_SPEC_OBSERVER_LABEL, (void*)&&ZEND_RECV_SPEC_UNUSED_LABEL, (void*)&&ZEND_RECV_INIT_SPEC_CONST_LABEL, - (void*)&&ZEND_SEND_VAL_SPEC_CONST_LABEL, - (void*)&&ZEND_SEND_VAL_SPEC_TMPVAR_LABEL, - (void*)&&ZEND_SEND_VAL_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_SEND_VAL_SPEC_CONST_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAL_SPEC_CONST_UNUSED_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAL_SPEC_TMPVAR_CONST_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAL_SPEC_TMPVAR_CONST_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_SEND_VAR_EX_SPEC_VAR_LABEL, - (void*)&&ZEND_SEND_VAR_EX_SPEC_VAR_QUICK_LABEL, (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_SEND_VAR_EX_SPEC_CV_LABEL, - (void*)&&ZEND_SEND_VAR_EX_SPEC_CV_QUICK_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_SEND_REF_SPEC_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_SEND_REF_SPEC_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SPEC_CV_CONST_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SPEC_CV_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_REF_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_REF_SPEC_VAR_UNUSED_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_REF_SPEC_CV_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_REF_SPEC_CV_UNUSED_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NEW_SPEC_CONST_UNUSED_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NEW_SPEC_VAR_UNUSED_LABEL, @@ -51891,10 +52383,15 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_LABEL, (void*)&&ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_LABEL, (void*)&&ZEND_INCLUDE_OR_EVAL_SPEC_CONST_LABEL, + (void*)&&ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_LABEL, (void*)&&ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_LABEL, (void*)&&ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_INCLUDE_OR_EVAL_SPEC_CV_LABEL, + (void*)&&ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_LABEL, (void*)&&ZEND_UNSET_VAR_SPEC_CONST_UNUSED_LABEL, (void*)&&ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_LABEL, (void*)&&ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_LABEL, @@ -52313,18 +52810,30 @@ 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_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_LABEL, + (void*)&&ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_LABEL, + (void*)&&ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_EXT_STMT_SPEC_LABEL, (void*)&&ZEND_EXT_FCALL_BEGIN_SPEC_LABEL, (void*)&&ZEND_EXT_FCALL_END_SPEC_LABEL, (void*)&&ZEND_EXT_NOP_SPEC_LABEL, (void*)&&ZEND_TICKS_SPEC_LABEL, - (void*)&&ZEND_SEND_VAR_NO_REF_SPEC_VAR_LABEL, + (void*)&&ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_CATCH_SPEC_CONST_LABEL, (void*)&&ZEND_THROW_SPEC_CONST_LABEL, - (void*)&&ZEND_THROW_SPEC_TMP_LABEL, - (void*)&&ZEND_THROW_SPEC_VAR_LABEL, + (void*)&&ZEND_THROW_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_THROW_SPEC_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_THROW_SPEC_CV_LABEL, (void*)&&ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_LABEL, @@ -52338,10 +52847,15 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_CLONE_SPEC_UNUSED_LABEL, (void*)&&ZEND_CLONE_SPEC_CV_LABEL, (void*)&&ZEND_RETURN_BY_REF_SPEC_CONST_LABEL, + (void*)&&ZEND_RETURN_BY_REF_SPEC_OBSERVER_LABEL, (void*)&&ZEND_RETURN_BY_REF_SPEC_TMP_LABEL, + (void*)&&ZEND_RETURN_BY_REF_SPEC_OBSERVER_LABEL, (void*)&&ZEND_RETURN_BY_REF_SPEC_VAR_LABEL, + (void*)&&ZEND_RETURN_BY_REF_SPEC_OBSERVER_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_RETURN_BY_REF_SPEC_CV_LABEL, + (void*)&&ZEND_RETURN_BY_REF_SPEC_OBSERVER_LABEL, (void*)&&ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_LABEL, (void*)&&ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_LABEL, @@ -52422,10 +52936,43 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_LABEL, - (void*)&&ZEND_SEND_VAL_EX_SPEC_CONST_LABEL, - (void*)&&ZEND_SEND_VAL_EX_SPEC_CONST_QUICK_LABEL, - (void*)&&ZEND_SEND_VAL_EX_SPEC_TMP_LABEL, - (void*)&&ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_LABEL, + (void*)&&ZEND_SEND_VAL_EX_SPEC_CONST_CONST_LABEL, + (void*)&&ZEND_SEND_VAL_EX_SPEC_CONST_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_LABEL, + (void*)&&ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAL_EX_SPEC_TMP_CONST_LABEL, + (void*)&&ZEND_SEND_VAL_EX_SPEC_TMP_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_LABEL, + (void*)&&ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -52434,9 +52981,36 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_SEND_VAR_SPEC_VAR_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_SEND_VAR_SPEC_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_SPEC_VAR_UNUSED_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_SPEC_CV_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_VAR_SPEC_CV_UNUSED_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_INIT_USER_CALL_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_LABEL, (void*)&&ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_LABEL, @@ -52480,8 +53054,12 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_DO_ICALL_SPEC_RETVAL_USED_LABEL, (void*)&&ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_LABEL, (void*)&&ZEND_DO_UCALL_SPEC_RETVAL_USED_LABEL, + (void*)&&ZEND_DO_UCALL_SPEC_OBSERVER_LABEL, + (void*)&&ZEND_DO_UCALL_SPEC_OBSERVER_LABEL, (void*)&&ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_LABEL, (void*)&&ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_LABEL, + (void*)&&ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_LABEL, + (void*)&&ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -52618,46 +53196,56 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_FETCH_LIST_W_SPEC_VAR_CV_LABEL, (void*)&&ZEND_SEPARATE_SPEC_VAR_UNUSED_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_LABEL, (void*)&&ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_LABEL, + (void*)&&ZEND_FETCH_CLASS_NAME_SPEC_CV_LABEL, (void*)&&ZEND_CALL_TRAMPOLINE_SPEC_LABEL, + (void*)&&ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_LABEL, (void*)&&ZEND_DISCARD_EXCEPTION_SPEC_LABEL, (void*)&&ZEND_YIELD_SPEC_CONST_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_CONST_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_CONST_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_CONST_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_CONST_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_CONST_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_CONST_CV_LABEL, (void*)&&ZEND_YIELD_SPEC_TMP_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_TMP_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_TMP_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_TMP_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_TMP_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_TMP_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_TMP_CV_LABEL, (void*)&&ZEND_YIELD_SPEC_VAR_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_VAR_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_VAR_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_VAR_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_VAR_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_VAR_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_VAR_CV_LABEL, (void*)&&ZEND_YIELD_SPEC_UNUSED_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_UNUSED_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_UNUSED_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_UNUSED_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_UNUSED_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_UNUSED_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_UNUSED_CV_LABEL, (void*)&&ZEND_YIELD_SPEC_CV_CONST_LABEL, - (void*)&&ZEND_YIELD_SPEC_CV_TMP_LABEL, - (void*)&&ZEND_YIELD_SPEC_CV_VAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_CV_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_SPEC_CV_TMPVAR_LABEL, (void*)&&ZEND_YIELD_SPEC_CV_UNUSED_LABEL, (void*)&&ZEND_YIELD_SPEC_CV_CV_LABEL, (void*)&&ZEND_GENERATOR_RETURN_SPEC_CONST_LABEL, + (void*)&&ZEND_GENERATOR_RETURN_SPEC_OBSERVER_LABEL, (void*)&&ZEND_GENERATOR_RETURN_SPEC_TMP_LABEL, + (void*)&&ZEND_GENERATOR_RETURN_SPEC_OBSERVER_LABEL, (void*)&&ZEND_GENERATOR_RETURN_SPEC_VAR_LABEL, + (void*)&&ZEND_GENERATOR_RETURN_SPEC_OBSERVER_LABEL, + (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_GENERATOR_RETURN_SPEC_CV_LABEL, + (void*)&&ZEND_GENERATOR_RETURN_SPEC_OBSERVER_LABEL, (void*)&&ZEND_FAST_CALL_SPEC_LABEL, (void*)&&ZEND_FAST_RET_SPEC_LABEL, (void*)&&ZEND_RECV_VARIADIC_SPEC_UNUSED_LABEL, (void*)&&ZEND_SEND_UNPACK_SPEC_LABEL, (void*)&&ZEND_YIELD_FROM_SPEC_CONST_LABEL, - (void*)&&ZEND_YIELD_FROM_SPEC_TMP_LABEL, - (void*)&&ZEND_YIELD_FROM_SPEC_VAR_LABEL, + (void*)&&ZEND_YIELD_FROM_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_YIELD_FROM_SPEC_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_YIELD_FROM_SPEC_CV_LABEL, (void*)&&ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_LABEL, @@ -52714,7 +53302,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_BIND_LEXICAL_SPEC_TMP_CV_LABEL, (void*)&&ZEND_BIND_STATIC_SPEC_CV_UNUSED_LABEL, (void*)&&ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_LABEL, - (void*)&&ZEND_SEND_FUNC_ARG_SPEC_VAR_LABEL, + (void*)&&ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_LABEL, + (void*)&&ZEND_NULL_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, @@ -52772,6 +53364,48 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_LABEL, + (void*)&&ZEND_MATCH_SPEC_CONST_CONST_LABEL, + (void*)&&ZEND_MATCH_SPEC_TMPVARCV_CONST_LABEL, + (void*)&&ZEND_MATCH_SPEC_TMPVARCV_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_MATCH_SPEC_TMPVARCV_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_CASE_STRICT_SPEC_TMP_CONST_LABEL, + (void*)&&ZEND_CASE_STRICT_SPEC_TMP_TMP_LABEL, + (void*)&&ZEND_CASE_STRICT_SPEC_TMP_VAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_CASE_STRICT_SPEC_TMP_CV_LABEL, + (void*)&&ZEND_CASE_STRICT_SPEC_VAR_CONST_LABEL, + (void*)&&ZEND_CASE_STRICT_SPEC_VAR_TMP_LABEL, + (void*)&&ZEND_CASE_STRICT_SPEC_VAR_VAR_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_CASE_STRICT_SPEC_VAR_CV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_LABEL, + (void*)&&ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_LABEL, + (void*)&&ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_LABEL, + (void*)&&ZEND_JMP_NULL_SPEC_CONST_LABEL, + (void*)&&ZEND_JMP_NULL_SPEC_TMPVARCV_LABEL, + (void*)&&ZEND_JMP_NULL_SPEC_TMPVARCV_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_JMP_NULL_SPEC_TMPVARCV_LABEL, + (void*)&&ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_LABEL, + (void*)&&ZEND_RECV_NOTYPE_SPEC_LABEL, (void*)&&ZEND_JMP_FORWARD_SPEC_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -53298,6 +53932,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_LABEL, (void*)&&ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_LABEL, (void*)&&ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_LABEL, + (void*)&&ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_LABEL, + (void*)&&ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_NULL_LABEL, + (void*)&&ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -53657,9 +54301,9 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_SEND_VAR_SIMPLE_SPEC_CV_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_LABEL, + (void*)&&ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED_LABEL, (void*)&&ZEND_SEND_VAL_SIMPLE_SPEC_CONST_LABEL, (void*)&&ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_LABEL, (void*)&&ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_LABEL, @@ -53754,7 +54398,7 @@ zend_leave_helper_SPEC_LABEL: uint32_t call_info = EX_CALL_INFO(); SAVE_OPLINE(); - if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED)) == 0)) { + if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); i_free_compiled_variables(execute_data); @@ -53787,6 +54431,10 @@ zend_leave_helper_SPEC_LABEL: zend_clean_and_cache_symbol_table(EX(symbol_table)); } + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(EX(extra_named_params)); + } + /* Free extra args before releasing the closure, * as that may free the op_array. */ zend_vm_stack_free_extra_args_ex(call_info, execute_data); @@ -53834,11 +54482,14 @@ zend_leave_helper_SPEC_LABEL: #ifdef ZEND_PREFER_RELOAD call_info = EX_CALL_INFO(); #endif - if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS))) { if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_clean_and_cache_symbol_table(EX(symbol_table)); } zend_vm_stack_free_extra_args_ex(call_info, execute_data); + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(EX(extra_named_params)); + } } if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); @@ -53884,6 +54535,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_DO_UCALL_SPEC_RETVAL_USED) ZEND_DO_UCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_DO_UCALL_SPEC_OBSERVER): + VM_TRACE(ZEND_DO_UCALL_SPEC_OBSERVER) + ZEND_DO_UCALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED): VM_TRACE(ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED) ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53892,6 +54547,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED) ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER): + VM_TRACE(ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER) + ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_DO_FCALL_SPEC_RETVAL_UNUSED): VM_TRACE(ZEND_DO_FCALL_SPEC_RETVAL_UNUSED) ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53900,6 +54559,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_DO_FCALL_SPEC_RETVAL_USED) ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_DO_FCALL_SPEC_OBSERVER): + VM_TRACE(ZEND_DO_FCALL_SPEC_OBSERVER) + ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_GENERATOR_CREATE_SPEC): VM_TRACE(ZEND_GENERATOR_CREATE_SPEC) ZEND_GENERATOR_CREATE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53912,6 +54575,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_SEND_ARRAY_SPEC) ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_RECV_NOTYPE_SPEC): + VM_TRACE(ZEND_RECV_NOTYPE_SPEC) + ZEND_RECV_NOTYPE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ADD_ARRAY_UNPACK_SPEC): VM_TRACE(ZEND_ADD_ARRAY_UNPACK_SPEC) ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -53992,6 +54659,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_CALL_TRAMPOLINE_SPEC) ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER): + VM_TRACE(ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER) + ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_JMP_FORWARD_SPEC): VM_TRACE(ZEND_JMP_FORWARD_SPEC) ZEND_JMP_FORWARD_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54070,10 +54741,10 @@ zend_leave_helper_SPEC_LABEL: USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = RT_CONSTANT(opline, opline->op1); return_value = EX(return_value); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -54082,9 +54753,9 @@ zend_leave_helper_SPEC_LABEL: } } else if (!return_value) { if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -54099,7 +54770,7 @@ zend_leave_helper_SPEC_LABEL: do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { @@ -54135,6 +54806,87 @@ zend_leave_helper_SPEC_LABEL: } } } + + + + goto zend_leave_helper_SPEC_LABEL; +} + + HYBRID_CASE(ZEND_RETURN_SPEC_OBSERVER): + VM_TRACE(ZEND_RETURN_SPEC_OBSERVER) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + zval observer_retval; + + retval_ptr = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); + return_value = EX(return_value); + if (!return_value) { return_value = &observer_retval; }; + if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); + } + } + } else { + if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (opline->op1_type == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (opline->op1_type == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (opline->op1_type == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } + } + } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, return_value); + if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; goto zend_leave_helper_SPEC_LABEL; } @@ -54142,10 +54894,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_RETURN_BY_REF_SPEC_CONST) ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_RETURN_BY_REF_SPEC_OBSERVER): + VM_TRACE(ZEND_RETURN_BY_REF_SPEC_OBSERVER) + ZEND_RETURN_BY_REF_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_GENERATOR_RETURN_SPEC_CONST): VM_TRACE(ZEND_GENERATOR_RETURN_SPEC_CONST) ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_GENERATOR_RETURN_SPEC_OBSERVER): + VM_TRACE(ZEND_GENERATOR_RETURN_SPEC_OBSERVER) + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_THROW_SPEC_CONST): VM_TRACE(ZEND_THROW_SPEC_CONST) ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54154,18 +54914,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_CATCH_SPEC_CONST) ZEND_CATCH_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_SPEC_CONST): - VM_TRACE(ZEND_SEND_VAL_SPEC_CONST) - ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_CONST): - VM_TRACE(ZEND_SEND_VAL_EX_SPEC_CONST) - ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_CONST_QUICK): - VM_TRACE(ZEND_SEND_VAL_EX_SPEC_CONST_QUICK) - ZEND_SEND_VAL_EX_SPEC_CONST_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_USER_SPEC_CONST): VM_TRACE(ZEND_SEND_USER_SPEC_CONST) ZEND_SEND_USER_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54186,6 +54934,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INCLUDE_OR_EVAL_SPEC_CONST) ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER): + VM_TRACE(ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER) + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FE_RESET_R_SPEC_CONST): VM_TRACE(ZEND_FE_RESET_R_SPEC_CONST) ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54202,6 +54954,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_COALESCE_SPEC_CONST) ZEND_COALESCE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_JMP_NULL_SPEC_CONST): + VM_TRACE(ZEND_JMP_NULL_SPEC_CONST) + ZEND_JMP_NULL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_QM_ASSIGN_SPEC_CONST): VM_TRACE(ZEND_QM_ASSIGN_SPEC_CONST) ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54366,6 +55122,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INIT_USER_CALL_SPEC_CONST_CONST) ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_SPEC_CONST_CONST): + VM_TRACE(ZEND_SEND_VAL_SPEC_CONST_CONST) + ZEND_SEND_VAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_CONST_CONST): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_CONST_CONST) + ZEND_SEND_VAL_EX_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST): VM_TRACE(ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST) ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54410,6 +55174,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_SWITCH_STRING_SPEC_CONST_CONST) ZEND_SWITCH_STRING_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_MATCH_SPEC_CONST_CONST): + VM_TRACE(ZEND_MATCH_SPEC_CONST_CONST) + ZEND_MATCH_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IN_ARRAY_SPEC_CONST_CONST): VM_TRACE(ZEND_IN_ARRAY_SPEC_CONST_CONST) ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54602,13 +55370,9 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR) ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_CONST_TMP): - VM_TRACE(ZEND_YIELD_SPEC_CONST_TMP) - ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_CONST_VAR): - VM_TRACE(ZEND_YIELD_SPEC_CONST_VAR) - ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_CASE(ZEND_YIELD_SPEC_CONST_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_CONST_TMPVAR) + ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_R_SPEC_CONST_UNUSED): VM_TRACE(ZEND_FETCH_R_SPEC_CONST_UNUSED) @@ -54646,6 +55410,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED) ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_SPEC_CONST_UNUSED): + VM_TRACE(ZEND_SEND_VAL_SPEC_CONST_UNUSED) + ZEND_SEND_VAL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED) + ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK) + ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_NEW_SPEC_CONST_UNUSED): VM_TRACE(ZEND_NEW_SPEC_CONST_UNUSED) ZEND_NEW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54674,6 +55450,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_YIELD_SPEC_CONST_UNUSED) ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_MATCH_ERROR_SPEC_CONST_UNUSED): + VM_TRACE(ZEND_MATCH_ERROR_SPEC_CONST_UNUSED) + ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_COUNT_SPEC_CONST_UNUSED): VM_TRACE(ZEND_COUNT_SPEC_CONST_UNUSED) ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54774,6 +55554,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_YIELD_SPEC_CONST_CV) ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_BW_NOT_SPEC_TMPVARCV): + VM_TRACE(ZEND_BW_NOT_SPEC_TMPVARCV) + ZEND_BW_NOT_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_JMP_NULL_SPEC_TMPVARCV): + VM_TRACE(ZEND_JMP_NULL_SPEC_TMPVARCV) + ZEND_JMP_NULL_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV): VM_TRACE(ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -54858,6 +55646,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST) ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_MATCH_SPEC_TMPVARCV_CONST): + VM_TRACE(ZEND_MATCH_SPEC_TMPVARCV_CONST) + ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST): VM_TRACE(ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55186,14 +55978,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR) ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED): + VM_TRACE(ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED) + ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV): VM_TRACE(ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV) ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_BW_NOT_SPEC_TMPVAR): - VM_TRACE(ZEND_BW_NOT_SPEC_TMPVAR) - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_BOOL_NOT_SPEC_TMPVAR): VM_TRACE(ZEND_BOOL_NOT_SPEC_TMPVAR) ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55230,9 +56022,9 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FE_FREE_SPEC_TMPVAR) ZEND_FE_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_SPEC_TMPVAR): - VM_TRACE(ZEND_SEND_VAL_SPEC_TMPVAR) - ZEND_SEND_VAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_CASE(ZEND_THROW_SPEC_TMPVAR): + VM_TRACE(ZEND_THROW_SPEC_TMPVAR) + ZEND_THROW_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); HYBRID_CASE(ZEND_BOOL_SPEC_TMPVAR): VM_TRACE(ZEND_BOOL_SPEC_TMPVAR) @@ -55246,6 +56038,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR) ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_FROM_SPEC_TMPVAR): + VM_TRACE(ZEND_YIELD_FROM_SPEC_TMPVAR) + ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_STRLEN_SPEC_TMPVAR): VM_TRACE(ZEND_STRLEN_SPEC_TMPVAR) ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55254,6 +56050,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_TYPE_CHECK_SPEC_TMPVAR) ZEND_TYPE_CHECK_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR): + VM_TRACE(ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR) + ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_DIV_SPEC_TMPVAR_CONST): VM_TRACE(ZEND_DIV_SPEC_TMPVAR_CONST) ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55322,6 +56122,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST) ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_SPEC_TMPVAR_CONST): + VM_TRACE(ZEND_SEND_VAL_SPEC_TMPVAR_CONST) + ZEND_SEND_VAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_CASE_SPEC_TMPVAR_CONST): VM_TRACE(ZEND_CASE_SPEC_TMPVAR_CONST) ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55462,6 +56266,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED) ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED): + VM_TRACE(ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED) + ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED): VM_TRACE(ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED) ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55548,10 +56356,10 @@ zend_leave_helper_SPEC_LABEL: USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -55560,9 +56368,9 @@ zend_leave_helper_SPEC_LABEL: } } else if (!return_value) { if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -55577,7 +56385,7 @@ zend_leave_helper_SPEC_LABEL: do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { @@ -55613,6 +56421,9 @@ zend_leave_helper_SPEC_LABEL: } } } + + + goto zend_leave_helper_SPEC_LABEL; } @@ -55624,18 +56435,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_GENERATOR_RETURN_SPEC_TMP) ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_THROW_SPEC_TMP): - VM_TRACE(ZEND_THROW_SPEC_TMP) - ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP): - VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP) - ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_QUICK): - VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_QUICK) - ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_USER_SPEC_TMP): VM_TRACE(ZEND_SEND_USER_SPEC_TMP) ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55668,14 +56467,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_QM_ASSIGN_SPEC_TMP) ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_FROM_SPEC_TMP): - VM_TRACE(ZEND_YIELD_FROM_SPEC_TMP) - ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST) ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_CONST): + VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_CONST) + ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST): VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST) ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55696,6 +56495,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ROPE_END_SPEC_TMP_CONST) ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_CONST): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_CONST) + ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST): VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST) ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55736,21 +56539,25 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR) ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_TMP_TMPVAR) + ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP) ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_TMP): + VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_TMP) + ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP): VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP) ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_TMP_TMP): - VM_TRACE(ZEND_YIELD_SPEC_TMP_TMP) - ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_TMP_VAR): - VM_TRACE(ZEND_YIELD_SPEC_TMP_VAR) - ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_VAR): + VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_VAR) + ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED): VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED) @@ -55760,6 +56567,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED) ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED) + ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK) + ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED): VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED) ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55776,6 +56591,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_GET_TYPE_SPEC_TMP_UNUSED) ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_CV): + VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_CV) + ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV): VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV) ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55838,10 +56657,10 @@ zend_leave_helper_SPEC_LABEL: USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; - retval_ptr = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -55850,9 +56669,9 @@ zend_leave_helper_SPEC_LABEL: } } else if (!return_value) { if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -55867,7 +56686,7 @@ zend_leave_helper_SPEC_LABEL: do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { @@ -55903,6 +56722,9 @@ zend_leave_helper_SPEC_LABEL: } } } + + + goto zend_leave_helper_SPEC_LABEL; } @@ -55914,42 +56736,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_GENERATOR_RETURN_SPEC_VAR) ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_THROW_SPEC_VAR): - VM_TRACE(ZEND_THROW_SPEC_VAR) - ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_SPEC_VAR): - VM_TRACE(ZEND_SEND_VAR_SPEC_VAR) - ZEND_SEND_VAR_SPEC_VAR_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_NO_REF_SPEC_VAR): - VM_TRACE(ZEND_SEND_VAR_NO_REF_SPEC_VAR) - ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR): - VM_TRACE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR) - ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK): - VM_TRACE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK) - ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_REF_SPEC_VAR): - VM_TRACE(ZEND_SEND_REF_SPEC_VAR) - ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_VAR): - VM_TRACE(ZEND_SEND_VAR_EX_SPEC_VAR) - ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_VAR_QUICK): - VM_TRACE(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): - VM_TRACE(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): VM_TRACE(ZEND_SEND_USER_SPEC_VAR) ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55986,22 +56772,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_QM_ASSIGN_SPEC_VAR) ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_FROM_SPEC_VAR): - VM_TRACE(ZEND_YIELD_FROM_SPEC_VAR) - ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_VAR_SIMPLE_SPEC_VAR): VM_TRACE(ZEND_SEND_VAR_SIMPLE_SPEC_VAR) ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR): - VM_TRACE(ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR) - ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_VAR_CONST): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_VAR_CONST) ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_VAR_CONST): + VM_TRACE(ZEND_CASE_STRICT_SPEC_VAR_CONST) + ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST): VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST) ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56114,6 +56896,30 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST) ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_SPEC_VAR_CONST): + VM_TRACE(ZEND_SEND_VAR_SPEC_VAR_CONST) + ZEND_SEND_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST): + VM_TRACE(ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST) + ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST): + VM_TRACE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST) + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_REF_SPEC_VAR_CONST): + VM_TRACE(ZEND_SEND_REF_SPEC_VAR_CONST) + ZEND_SEND_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_VAR_CONST): + VM_TRACE(ZEND_SEND_VAR_EX_SPEC_VAR_CONST) + ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST): + VM_TRACE(ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST) + ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST): VM_TRACE(ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST) ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56258,10 +57064,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR) ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_VAR_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_VAR_TMPVAR) + ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_VAR_TMP): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_VAR_TMP) ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_VAR_TMP): + VM_TRACE(ZEND_CASE_STRICT_SPEC_VAR_TMP) + ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP): VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP) ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56274,14 +57088,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED) ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_VAR_TMP): - VM_TRACE(ZEND_YIELD_SPEC_VAR_TMP) - ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_VAR_VAR): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_VAR_VAR) ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_VAR_VAR): + VM_TRACE(ZEND_CASE_STRICT_SPEC_VAR_VAR) + ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR): VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR) ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56298,10 +57112,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_REF_SPEC_VAR_VAR) ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_VAR_VAR): - VM_TRACE(ZEND_YIELD_SPEC_VAR_VAR) - ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED): VM_TRACE(ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED) ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56342,6 +57152,38 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED) ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_SPEC_VAR_UNUSED): + VM_TRACE(ZEND_SEND_VAR_SPEC_VAR_UNUSED) + ZEND_SEND_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED): + VM_TRACE(ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED) + ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED): + VM_TRACE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED) + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK): + VM_TRACE(ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK) + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_REF_SPEC_VAR_UNUSED): + VM_TRACE(ZEND_SEND_REF_SPEC_VAR_UNUSED) + ZEND_SEND_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED): + VM_TRACE(ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED) + ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK): + VM_TRACE(ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK) + ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED): + VM_TRACE(ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED) + ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_NEW_SPEC_VAR_UNUSED): VM_TRACE(ZEND_NEW_SPEC_VAR_UNUSED) ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56370,6 +57212,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_GET_TYPE_SPEC_VAR_UNUSED) ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED): + VM_TRACE(ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) + ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_VAR_CV): + VM_TRACE(ZEND_CASE_STRICT_SPEC_VAR_CV) + ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV): VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV) ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56510,14 +57360,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(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): - VM_TRACE(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): - VM_TRACE(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_CLONE_SPEC_UNUSED): VM_TRACE(ZEND_CLONE_SPEC_UNUSED) ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56602,6 +57444,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST) ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST): + VM_TRACE(ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST) + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST): VM_TRACE(ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST) ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56714,13 +57560,9 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR) ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_UNUSED_TMP): - VM_TRACE(ZEND_YIELD_SPEC_UNUSED_TMP) - ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_UNUSED_VAR): - VM_TRACE(ZEND_YIELD_SPEC_UNUSED_VAR) - ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_CASE(ZEND_YIELD_SPEC_UNUSED_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_UNUSED_TMPVAR) + ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED): VM_TRACE(ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED) @@ -56734,6 +57576,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED) ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED): + VM_TRACE(ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED) + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK): + VM_TRACE(ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK) + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED): + VM_TRACE(ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED) + ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_NEW_SPEC_UNUSED_UNUSED): VM_TRACE(ZEND_NEW_SPEC_UNUSED_UNUSED) ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56862,10 +57716,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_YIELD_SPEC_UNUSED_CV) ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_BW_NOT_SPEC_CV): - VM_TRACE(ZEND_BW_NOT_SPEC_CV) - ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_BOOL_NOT_SPEC_CV): VM_TRACE(ZEND_BOOL_NOT_SPEC_CV) ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56924,10 +57774,10 @@ zend_leave_helper_SPEC_LABEL: USE_OPLINE zval *retval_ptr; zval *return_value; - zend_free_op free_op1; retval_ptr = EX_VAR(opline->op1.var); return_value = EX(return_value); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -56936,9 +57786,9 @@ zend_leave_helper_SPEC_LABEL: } } else if (!return_value) { if (IS_CV & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(free_op1)); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); } } } else { @@ -56953,7 +57803,7 @@ zend_leave_helper_SPEC_LABEL: do { if (Z_OPT_REFCOUNTED_P(retval_ptr)) { if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { @@ -56989,6 +57839,9 @@ zend_leave_helper_SPEC_LABEL: } } } + + + goto zend_leave_helper_SPEC_LABEL; } @@ -57004,22 +57857,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_THROW_SPEC_CV) ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_SPEC_CV): - VM_TRACE(ZEND_SEND_VAR_SPEC_CV) - ZEND_SEND_VAR_SPEC_CV_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_REF_SPEC_CV): - VM_TRACE(ZEND_SEND_REF_SPEC_CV) - ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_CV): - VM_TRACE(ZEND_SEND_VAR_EX_SPEC_CV) - ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_CV_QUICK): - VM_TRACE(ZEND_SEND_VAR_EX_SPEC_CV_QUICK) - ZEND_SEND_VAR_EX_SPEC_CV_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_USER_SPEC_CV): VM_TRACE(ZEND_SEND_USER_SPEC_CV) ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57072,6 +57909,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_TYPE_CHECK_SPEC_CV) ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_CLASS_NAME_SPEC_CV): + VM_TRACE(ZEND_FETCH_CLASS_NAME_SPEC_CV) + ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED): VM_TRACE(ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57124,10 +57965,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_SEND_VAR_SIMPLE_SPEC_CV) ZEND_SEND_VAR_SIMPLE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV): - VM_TRACE(ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV) - ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_DIV_SPEC_CV_CONST): VM_TRACE(ZEND_DIV_SPEC_CV_CONST) ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57304,6 +58141,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INIT_METHOD_CALL_SPEC_CV_CONST) ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_SPEC_CV_CONST): + VM_TRACE(ZEND_SEND_VAR_SPEC_CV_CONST) + ZEND_SEND_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_REF_SPEC_CV_CONST): + VM_TRACE(ZEND_SEND_REF_SPEC_CV_CONST) + ZEND_SEND_REF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_CV_CONST): + VM_TRACE(ZEND_SEND_VAR_EX_SPEC_CV_CONST) + ZEND_SEND_VAR_EX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST): VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST) ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57348,6 +58197,14 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_IN_ARRAY_SPEC_CV_CONST) ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST): + VM_TRACE(ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) + ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST): + VM_TRACE(ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) + ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST): VM_TRACE(ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57544,6 +58401,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR) ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_CV_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_CV_TMPVAR) + ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_CV_TMP): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_CV_TMP) ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57560,10 +58421,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED) ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_CV_TMP): - VM_TRACE(ZEND_YIELD_SPEC_CV_TMP) - ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_CV_VAR): VM_TRACE(ZEND_IS_IDENTICAL_SPEC_CV_VAR) ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57588,10 +58445,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INSTANCEOF_SPEC_CV_VAR) ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_CV_VAR): - VM_TRACE(ZEND_YIELD_SPEC_CV_VAR) - ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED): VM_TRACE(ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED) ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57652,6 +58505,22 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED) ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_SPEC_CV_UNUSED): + VM_TRACE(ZEND_SEND_VAR_SPEC_CV_UNUSED) + ZEND_SEND_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_REF_SPEC_CV_UNUSED): + VM_TRACE(ZEND_SEND_REF_SPEC_CV_UNUSED) + ZEND_SEND_REF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_CV_UNUSED): + VM_TRACE(ZEND_SEND_VAR_EX_SPEC_CV_UNUSED) + ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK): + VM_TRACE(ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK) + ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED): VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED) ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57712,6 +58581,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_GET_TYPE_SPEC_CV_UNUSED) ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED): + VM_TRACE(ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) + ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_DIV_SPEC_CV_CV): VM_TRACE(ZEND_DIV_SPEC_CV_CV) ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57924,12 +58797,20 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_YIELD_SPEC_CV_CV) ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV): + VM_TRACE(ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) + ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV): + VM_TRACE(ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) + ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(HYBRID_HALT): #ifdef ZEND_VM_FP_GLOBAL_REG - execute_data = orig_execute_data; + execute_data = vm_stack_data.orig_execute_data; #endif #ifdef ZEND_VM_IP_GLOBAL_REG - opline = orig_opline; + opline = vm_stack_data.orig_opline; #endif return; HYBRID_DEFAULT: @@ -57938,9 +58819,9 @@ zend_leave_helper_SPEC_LABEL: HYBRID_BREAK(); /* Never reached */ #else #ifdef ZEND_VM_FP_GLOBAL_REG - execute_data = orig_execute_data; + execute_data = vm_stack_data.orig_execute_data; # ifdef ZEND_VM_IP_GLOBAL_REG - opline = orig_opline; + opline = vm_stack_data.orig_opline; # endif return; #else @@ -57949,7 +58830,7 @@ zend_leave_helper_SPEC_LABEL: ZEND_VM_LOOP_INTERRUPT_CHECK(); } else { # ifdef ZEND_VM_IP_GLOBAL_REG - opline = orig_opline; + opline = vm_stack_data.orig_opline; # endif return; } @@ -57990,7 +58871,9 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value) } EX(prev_execute_data) = EG(current_execute_data); i_init_code_execute_data(execute_data, op_array, return_value); + ZEND_OBSERVER_FCALL_BEGIN(execute_data); zend_execute_ex(execute_data); + /* Observer end handlers are called from ZEND_RETURN */ zend_vm_stack_free_call_frame(execute_data); } @@ -58300,10 +59183,10 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_POW_SPEC_CV_CV_HANDLER, ZEND_BW_NOT_SPEC_CONST_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, + ZEND_BW_NOT_SPEC_TMPVARCV_HANDLER, + ZEND_BW_NOT_SPEC_TMPVARCV_HANDLER, ZEND_NULL_HANDLER, - ZEND_BW_NOT_SPEC_CV_HANDLER, + ZEND_BW_NOT_SPEC_TMPVARCV_HANDLER, ZEND_BOOL_NOT_SPEC_CONST_HANDLER, ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, @@ -59285,8 +60168,16 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_CASE_SPEC_TMPVAR_CV_HANDLER, ZEND_CHECK_VAR_SPEC_CV_UNUSED_HANDLER, - ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_QUICK_HANDLER, + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_HANDLER, + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_HANDLER, + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_CAST_SPEC_CONST_HANDLER, ZEND_CAST_SPEC_TMP_HANDLER, ZEND_CAST_SPEC_VAR_HANDLER, @@ -59342,34 +60233,121 @@ void zend_vm_init(void) ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER, ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER, ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER, + ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER, + ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER, ZEND_INIT_FCALL_SPEC_CONST_HANDLER, ZEND_RETURN_SPEC_CONST_HANDLER, + ZEND_RETURN_SPEC_OBSERVER_HANDLER, ZEND_RETURN_SPEC_TMP_HANDLER, + ZEND_RETURN_SPEC_OBSERVER_HANDLER, ZEND_RETURN_SPEC_VAR_HANDLER, + ZEND_RETURN_SPEC_OBSERVER_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_RETURN_SPEC_CV_HANDLER, + ZEND_RETURN_SPEC_OBSERVER_HANDLER, ZEND_RECV_SPEC_UNUSED_HANDLER, ZEND_RECV_INIT_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_SPEC_TMPVAR_HANDLER, - ZEND_SEND_VAL_SPEC_TMPVAR_HANDLER, + ZEND_SEND_VAL_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAL_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_EX_SPEC_VAR_QUICK_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_SEND_VAR_EX_SPEC_CV_HANDLER, - ZEND_SEND_VAR_EX_SPEC_CV_QUICK_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_SEND_REF_SPEC_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_SEND_REF_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_CONST_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_REF_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_REF_SPEC_VAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_REF_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_REF_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, ZEND_NEW_SPEC_CONST_UNUSED_HANDLER, ZEND_NULL_HANDLER, ZEND_NEW_SPEC_VAR_UNUSED_HANDLER, @@ -59428,10 +60406,15 @@ void zend_vm_init(void) ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER, ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER, ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_HANDLER, ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_HANDLER, ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_HANDLER, ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER, ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER, ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER, @@ -59850,18 +60833,30 @@ void zend_vm_init(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_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER, + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_EXT_STMT_SPEC_HANDLER, ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, ZEND_EXT_FCALL_END_SPEC_HANDLER, ZEND_EXT_NOP_SPEC_HANDLER, ZEND_TICKS_SPEC_HANDLER, - ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, + ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, ZEND_CATCH_SPEC_CONST_HANDLER, ZEND_THROW_SPEC_CONST_HANDLER, - ZEND_THROW_SPEC_TMP_HANDLER, - ZEND_THROW_SPEC_VAR_HANDLER, + ZEND_THROW_SPEC_TMPVAR_HANDLER, + ZEND_THROW_SPEC_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_THROW_SPEC_CV_HANDLER, ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_HANDLER, @@ -59875,10 +60870,15 @@ void zend_vm_init(void) ZEND_CLONE_SPEC_UNUSED_HANDLER, ZEND_CLONE_SPEC_CV_HANDLER, ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER, + ZEND_RETURN_BY_REF_SPEC_OBSERVER_HANDLER, ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER, + ZEND_RETURN_BY_REF_SPEC_OBSERVER_HANDLER, ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER, + ZEND_RETURN_BY_REF_SPEC_OBSERVER_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, + ZEND_RETURN_BY_REF_SPEC_OBSERVER_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, @@ -59959,10 +60959,48 @@ void zend_vm_init(void) ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER, - ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_EX_SPEC_CONST_QUICK_HANDLER, - ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_CONST_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -59971,9 +61009,31 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_SEND_VAR_SPEC_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_SEND_VAR_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_SPEC_VAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER, ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER, ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER, @@ -60017,8 +61077,12 @@ void zend_vm_init(void) ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER, ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER, ZEND_DO_UCALL_SPEC_RETVAL_USED_HANDLER, + ZEND_DO_UCALL_SPEC_OBSERVER_HANDLER, + ZEND_DO_UCALL_SPEC_OBSERVER_HANDLER, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_HANDLER, ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER, + ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_HANDLER, + ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -60155,46 +61219,56 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER, ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER, + ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER, ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_HANDLER, + ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDLER, ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, + ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_HANDLER, ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, ZEND_YIELD_SPEC_CONST_CONST_HANDLER, - ZEND_YIELD_SPEC_CONST_TMP_HANDLER, - ZEND_YIELD_SPEC_CONST_VAR_HANDLER, + ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER, ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER, ZEND_YIELD_SPEC_CONST_CV_HANDLER, ZEND_YIELD_SPEC_TMP_CONST_HANDLER, - ZEND_YIELD_SPEC_TMP_TMP_HANDLER, - ZEND_YIELD_SPEC_TMP_VAR_HANDLER, + ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER, ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER, ZEND_YIELD_SPEC_TMP_CV_HANDLER, ZEND_YIELD_SPEC_VAR_CONST_HANDLER, - ZEND_YIELD_SPEC_VAR_TMP_HANDLER, - ZEND_YIELD_SPEC_VAR_VAR_HANDLER, + ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER, ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER, ZEND_YIELD_SPEC_VAR_CV_HANDLER, ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER, - ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER, - ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER, ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER, ZEND_YIELD_SPEC_UNUSED_CV_HANDLER, ZEND_YIELD_SPEC_CV_CONST_HANDLER, - ZEND_YIELD_SPEC_CV_TMP_HANDLER, - ZEND_YIELD_SPEC_CV_VAR_HANDLER, + ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER, + ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER, ZEND_YIELD_SPEC_CV_UNUSED_HANDLER, ZEND_YIELD_SPEC_CV_CV_HANDLER, ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_HANDLER, ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_HANDLER, ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_HANDLER, ZEND_FAST_CALL_SPEC_HANDLER, ZEND_FAST_RET_SPEC_HANDLER, ZEND_RECV_VARIADIC_SPEC_UNUSED_HANDLER, ZEND_SEND_UNPACK_SPEC_HANDLER, ZEND_YIELD_FROM_SPEC_CONST_HANDLER, - ZEND_YIELD_FROM_SPEC_TMP_HANDLER, - ZEND_YIELD_FROM_SPEC_VAR_HANDLER, + ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER, + ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_YIELD_FROM_SPEC_CV_HANDLER, ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER, @@ -60251,7 +61325,11 @@ void zend_vm_init(void) ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER, ZEND_BIND_STATIC_SPEC_CV_UNUSED_HANDLER, ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_SEND_FUNC_ARG_SPEC_VAR_HANDLER, + ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER, ZEND_SWITCH_LONG_SPEC_CONST_CONST_HANDLER, ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_HANDLER, @@ -60309,6 +61387,48 @@ void zend_vm_init(void) ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_HANDLER, + ZEND_MATCH_SPEC_CONST_CONST_HANDLER, + ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER, + ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER, + ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER, + ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER, + ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER, + ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDLER, + ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_HANDLER, + ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER, + ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER, + ZEND_JMP_NULL_SPEC_CONST_HANDLER, + ZEND_JMP_NULL_SPEC_TMPVARCV_HANDLER, + ZEND_JMP_NULL_SPEC_TMPVARCV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMP_NULL_SPEC_TMPVARCV_HANDLER, + ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_RECV_NOTYPE_SPEC_HANDLER, ZEND_JMP_FORWARD_SPEC_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -60835,6 +61955,16 @@ void zend_vm_init(void) ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER, + ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER, + ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -61194,9 +62324,9 @@ void zend_vm_init(void) ZEND_SEND_VAR_SIMPLE_SPEC_CV_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER, + ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_HANDLER, + ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED_HANDLER, ZEND_SEND_VAL_SIMPLE_SPEC_CONST_HANDLER, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_HANDLER, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER, @@ -61254,152 +62384,157 @@ void zend_vm_init(void) 1276 | SPEC_RULE_OP1, 1281 | SPEC_RULE_OP2, 1286, - 1287 | SPEC_RULE_QUICK_ARG, - 1289 | SPEC_RULE_OP1, - 1294 | SPEC_RULE_OP1, - 1299 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1324 | SPEC_RULE_OP2, - 1329 | SPEC_RULE_OP2, - 1334 | SPEC_RULE_OP2, - 1339, - 1340, - 1341, - 1342 | SPEC_RULE_RETVAL, - 1344, - 1345 | SPEC_RULE_OP1, - 1350, - 1351, - 1352 | SPEC_RULE_OP1, - 1357 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG, - 1367 | SPEC_RULE_OP1, - 1372 | SPEC_RULE_OP1, - 1377, - 1378, - 1379 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1404 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1429 | SPEC_RULE_OP1, - 1434 | SPEC_RULE_OP1, - 1439 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1464 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1489 | SPEC_RULE_OP1, - 1494, - 1495, - 1496 | SPEC_RULE_OP1, - 1501 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1526 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1551 | SPEC_RULE_OP1, - 1556 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1581 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1606 | SPEC_RULE_OP1, - 1611 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1636 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1661 | SPEC_RULE_OP1, - 1666 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1691 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1716 | SPEC_RULE_OP1, - 1721 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1746 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1771 | SPEC_RULE_OP1, - 1776 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1801 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1826 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1851, - 1852 | SPEC_RULE_QUICK_ARG, - 1854, - 1855, - 1856, - 1857, - 1858, - 1859, - 1860, - 1861 | SPEC_RULE_OP1, - 1866 | SPEC_RULE_OP2, + 1287 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG, + 1297 | SPEC_RULE_OP1, + 1302 | SPEC_RULE_OP1, + 1307 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1332 | SPEC_RULE_OP2, + 1337 | SPEC_RULE_OP2, + 1342 | SPEC_RULE_OP2, + 1347, + 1348, + 1349, + 1350 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, + 1354, + 1355 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER, + 1365, + 1366, + 1367 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1392 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG, + 1442 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1467 | SPEC_RULE_OP1, + 1472, + 1473, + 1474 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1499 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1524 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER, + 1534 | SPEC_RULE_OP1, + 1539 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1564 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1589 | SPEC_RULE_OP1, + 1594, + 1595, + 1596 | SPEC_RULE_OP1, + 1601 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1626 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1651 | SPEC_RULE_OP1, + 1656 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1681 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1706 | SPEC_RULE_OP1, + 1711 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1736 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1761 | SPEC_RULE_OP1, + 1766 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1791 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1816 | SPEC_RULE_OP1, + 1821 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1846 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1871 | SPEC_RULE_OP1, - 1876 | SPEC_RULE_OP1, - 1881 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1906 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1931 | SPEC_RULE_OP1, - 1936 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 1961 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG, - 1971 | SPEC_RULE_OP1, - 1976 | SPEC_RULE_OP2, - 1981, - 1982 | SPEC_RULE_OP1, - 1987 | SPEC_RULE_OP1, - 1992, - 1993 | SPEC_RULE_OP1, - 1998 | SPEC_RULE_OP1, - 2003 | SPEC_RULE_OP1, - 2008, - 2009, - 2010 | SPEC_RULE_OP2, - 2015 | SPEC_RULE_RETVAL, - 2017 | SPEC_RULE_RETVAL, - 2019 | SPEC_RULE_RETVAL, - 2021 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2021 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2046 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2046 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2071 | SPEC_RULE_OP1, - 2076, - 2077 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2102, - 2103 | SPEC_RULE_OP1, - 2108, - 2109, - 2110, - 2111, - 2112, - 2113, - 2114, - 2115 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2140, - 2141, - 2142, - 2143 | SPEC_RULE_OP1, - 2148, - 2149 | SPEC_RULE_ISSET, - 2151 | SPEC_RULE_OP2, - 2156, - 2157, + 1876 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1901 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1926 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1951, + 1952 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG, + 1962, + 1963, + 1964, + 1965, + 1966, + 1967 | SPEC_RULE_OP2, + 1972, + 1973 | SPEC_RULE_OP1, + 1978 | SPEC_RULE_OP2, + 1983 | SPEC_RULE_OP1, + 1988 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER, + 1998 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2023 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2048 | SPEC_RULE_OP1, + 2053 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2078 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_QUICK_ARG, + 2128 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2153 | SPEC_RULE_OP2, 2158, - 2159, - 2160 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2185 | SPEC_RULE_OP1, - 2190, - 2191, - 2192, - 2193, - 2194 | SPEC_RULE_OP1, - 2199, - 2200, - 2201 | SPEC_RULE_OP1, - 2206 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 2231, - 2232 | SPEC_RULE_OP1, - 2237, - 2238, - 2239, - 2240, - 2241, - 2242, - 2243, - 2244, - 2245 | SPEC_RULE_OP1, - 2250, - 2251, - 2252, - 2253, - 2254, - 2255 | SPEC_RULE_OP1, - 2260 | SPEC_RULE_OP1, - 2265 | SPEC_RULE_OP1, - 2270 | SPEC_RULE_OP1, - 2275 | SPEC_RULE_OP1, - 2280, - 2281 | SPEC_RULE_OP1, - 2286 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 3203 + 2159 | SPEC_RULE_OP1, + 2164 | SPEC_RULE_OP1, + 2169, + 2170 | SPEC_RULE_OP1, + 2175 | SPEC_RULE_OP1, + 2180 | SPEC_RULE_OP1, + 2185, + 2186, + 2187 | SPEC_RULE_OP2, + 2192 | SPEC_RULE_RETVAL, + 2194 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, + 2198 | SPEC_RULE_RETVAL | SPEC_RULE_OBSERVER, + 2202 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2202 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2227 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2227 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2252 | SPEC_RULE_OP1, + 2257, + 2258 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2283, + 2284 | SPEC_RULE_OP1, + 2289, + 2290, + 2291, + 2292, + 2293, + 2294, + 2295, + 2296 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2321, + 2322, + 2323, + 2324 | SPEC_RULE_OP1, + 2329, + 2330 | SPEC_RULE_ISSET, + 2332 | SPEC_RULE_OP2, + 2337, + 2338 | SPEC_RULE_OP1, + 2343 | SPEC_RULE_OBSERVER, + 2345, + 2346 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2371 | SPEC_RULE_OP1 | SPEC_RULE_OBSERVER, + 2381, + 2382, + 2383, + 2384, + 2385 | SPEC_RULE_OP1, + 2390, + 2391, + 2392 | SPEC_RULE_OP1, + 2397 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2422, + 2423 | SPEC_RULE_OP1, + 2428, + 2429, + 2430, + 2431, + 2432, + 2433, + 2434, + 2435, + 2436 | SPEC_RULE_OP1, + 2441, + 2442, + 2443, + 2444 | SPEC_RULE_OP2, + 2449, + 2450 | SPEC_RULE_OP1, + 2455 | SPEC_RULE_OP1, + 2460 | SPEC_RULE_OP1, + 2465 | SPEC_RULE_OP1, + 2470 | SPEC_RULE_OP1, + 2475, + 2476 | SPEC_RULE_OP1, + 2481 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2506 | SPEC_RULE_OP1, + 2511 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2536 | SPEC_RULE_OP1, + 2541 | SPEC_RULE_OP1, + 2546, + 3450 }; #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) zend_opcode_handler_funcs = labels; @@ -61431,7 +62566,7 @@ static void init_opcode_serialiser(void) zval tmp; zend_handlers_table = malloc(sizeof(HashTable)); - zend_hash_init_ex(zend_handlers_table, zend_handlers_count, NULL, NULL, 1, 0); + zend_hash_init(zend_handlers_table, zend_handlers_count, NULL, NULL, 1); zend_hash_real_init(zend_handlers_table, 0); Z_TYPE_INFO(tmp) = IS_LONG; for (i = 0; i < zend_handlers_count; i++) { @@ -61489,7 +62624,7 @@ ZEND_API int zend_vm_kind(void) return ZEND_VM_KIND; } -static const void* ZEND_FASTCALL zend_vm_get_opcode_handler_ex(uint32_t spec, const zend_op* op) +static uint32_t ZEND_FASTCALL zend_vm_get_opcode_handler_idx(uint32_t spec, const zend_op* op) { static const int zend_vm_decode[] = { _UNUSED_CODE, /* 0 = IS_UNUSED */ @@ -61508,6 +62643,9 @@ static const void* ZEND_FASTCALL zend_vm_get_opcode_handler_ex(uint32_t spec, co if (spec & SPEC_EXTRA_MASK) { if (spec & SPEC_RULE_RETVAL) { offset = offset * 2 + (op->result_type != IS_UNUSED); + if ((spec & SPEC_RULE_OBSERVER) && ZEND_OBSERVER_ENABLED) { + offset += 2; + } } else if (spec & SPEC_RULE_QUICK_ARG) { offset = offset * 2 + (op->op2.num <= MAX_ARG_FLAG_NUM); } else if (spec & SPEC_RULE_OP_DATA) { @@ -61516,20 +62654,25 @@ static const void* ZEND_FASTCALL zend_vm_get_opcode_handler_ex(uint32_t spec, co offset = offset * 2 + (op->extended_value & ZEND_ISEMPTY); } else if (spec & SPEC_RULE_SMART_BRANCH) { offset = offset * 3; - if ((op+1)->opcode == ZEND_JMPZ) { + if (op->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR)) { offset += 1; - } else if ((op+1)->opcode == ZEND_JMPNZ) { + } else if (op->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR)) { offset += 2; } + } else if (spec & SPEC_RULE_OBSERVER) { + offset = offset * 2; + if (ZEND_OBSERVER_ENABLED) { + offset += 1; + } } } - return zend_opcode_handlers[(spec & SPEC_START_MASK) + offset]; + return (spec & SPEC_START_MASK) + offset; } #if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op) { - return zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op); + return zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)]; } #endif @@ -61537,35 +62680,7 @@ static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op) { uint32_t spec = zend_spec_handlers[opcode]; - static const int zend_vm_decode[] = { - _UNUSED_CODE, /* 0 = IS_UNUSED */ - _CONST_CODE, /* 1 = IS_CONST */ - _TMP_CODE, /* 2 = IS_TMP_VAR */ - _UNUSED_CODE, /* 3 */ - _VAR_CODE, /* 4 = IS_VAR */ - _UNUSED_CODE, /* 5 */ - _UNUSED_CODE, /* 6 */ - _UNUSED_CODE, /* 7 */ - _CV_CODE /* 8 = IS_CV */ - }; - uint32_t offset = 0; - if (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type]; - if (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type]; - if (spec & SPEC_EXTRA_MASK) { - if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type]; - else if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED); - else if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num <= MAX_ARG_FLAG_NUM); - else if (spec & SPEC_RULE_SMART_BRANCH) { - offset = offset * 3; - if ((op+1)->opcode == ZEND_JMPZ) { - offset += 1; - } else if ((op+1)->opcode == ZEND_JMPNZ) { - offset += 2; - } - } - else if (spec & SPEC_RULE_ISSET) offset = offset * 2 + (op->extended_value & ZEND_ISEMPTY); - } - return zend_opcode_handler_funcs[(spec & SPEC_START_MASK) + offset]; + return zend_opcode_handler_funcs[zend_vm_get_opcode_handler_idx(spec, op)]; } #endif @@ -61579,7 +62694,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler(zend_op* op) zend_swap_operands(op); } } - op->handler = zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op); + op->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)]; } ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint32_t op2_info, uint32_t res_info) @@ -61592,7 +62707,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 = 2312 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2549 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -61600,7 +62715,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 = 2337 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2574 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -61608,7 +62723,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 = 2362 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2599 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -61619,17 +62734,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 = 2387 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2624 | 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 = 2412 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2649 | 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 = 2437 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2674 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_MUL: @@ -61640,17 +62755,53 @@ 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 = 2462 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2699 | 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 = 2487 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2724 | 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 = 2749 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + } + break; + case ZEND_IS_IDENTICAL: + if (op->op1_type < op->op2_type) { + zend_swap_operands(op); + } + if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { + if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { + break; + } + spec = 2774 | 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 = 2512 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2849 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { + spec = 3074 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + } + break; + case ZEND_IS_NOT_IDENTICAL: + if (op->op1_type < op->op2_type) { + zend_swap_operands(op); + } + if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { + if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { + break; + } + spec = 2924 | 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 = 2999 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { + spec = 3079 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_EQUAL: @@ -61661,12 +62812,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 = 2537 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2774 | 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 = 2612 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2849 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_EQUAL: @@ -61677,12 +62828,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 = 2687 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2924 | 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 = 2762 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2999 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_SMALLER: @@ -61690,12 +62841,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 = 2837 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3084 | 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 = 2912 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3159 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_IS_SMALLER_OR_EQUAL: @@ -61703,69 +62854,74 @@ 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 = 2987 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3234 | 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 = 3062 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3309 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_QM_ASSIGN: if (op1_info == MAY_BE_LONG) { - spec = 3149 | SPEC_RULE_OP1; + spec = 3396 | SPEC_RULE_OP1; } else if (op1_info == MAY_BE_DOUBLE) { - spec = 3154 | SPEC_RULE_OP1; + spec = 3401 | SPEC_RULE_OP1; } else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) { - spec = 3159 | SPEC_RULE_OP1; + spec = 3406 | SPEC_RULE_OP1; } break; case ZEND_PRE_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3137 | SPEC_RULE_RETVAL; + spec = 3384 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3139 | SPEC_RULE_RETVAL; + spec = 3386 | SPEC_RULE_RETVAL; } break; case ZEND_PRE_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3141 | SPEC_RULE_RETVAL; + spec = 3388 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3143 | SPEC_RULE_RETVAL; + spec = 3390 | SPEC_RULE_RETVAL; } break; case ZEND_POST_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3145; + spec = 3392; } else if (op1_info == MAY_BE_LONG) { - spec = 3146; + spec = 3393; } break; case ZEND_POST_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3147; + spec = 3394; } else if (op1_info == MAY_BE_LONG) { - spec = 3148; + spec = 3395; } break; case ZEND_JMP: if (OP_JMP_ADDR(op, op->op1) > op) { - spec = 2311; + spec = 2548; + } + break; + case ZEND_RECV: + if (op->op2.num == MAY_BE_ANY) { + spec = 2547; } break; case ZEND_SEND_VAL: - if (op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3199; + if (op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { + spec = 3446; } break; case ZEND_SEND_VAR_EX: - if (op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3194 | SPEC_RULE_OP1; + if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { + spec = 3441 | SPEC_RULE_OP1; } 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 = 3201 | SPEC_RULE_RETVAL; + if (op->op2_type == IS_CV && (op1_info & (MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) { + spec = 3448 | SPEC_RULE_RETVAL; } break; case ZEND_FETCH_DIM_R: @@ -61773,25 +62929,23 @@ 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 = 3164 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3411 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_SEND_VAL_EX: - if (op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3200; + if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { + spec = 3447; } break; case ZEND_SEND_VAR: - if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3189 | SPEC_RULE_OP1; + if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { + spec = 3436 | SPEC_RULE_OP1; } break; case ZEND_BW_OR: case ZEND_BW_AND: case ZEND_BW_XOR: case ZEND_BOOL_XOR: - case ZEND_IS_IDENTICAL: - case ZEND_IS_NOT_IDENTICAL: if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -61806,7 +62960,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t default: break; } - op->handler = zend_vm_get_opcode_handler_ex(spec, op); + op->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(spec, op)]; } ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex) |
