diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index d0aaccec7ce2c..876fcc816f7d9 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -460,6 +460,18 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx opline->op2.constant = map[opline->op2.constant]; } switch (opline->opcode) { + case ZEND_RECV: + case ZEND_RECV_INIT: + case ZEND_RECV_VARIADIC: + if (1) { // TODO: only do this if we have a type AST! + opline->extended_value = cache_size; + cache_size += sizeof(void *); + } + break; + case ZEND_VERIFY_RETURN_TYPE: + opline->op2.num = cache_size; + cache_size += sizeof(void *); + break; case ZEND_ASSIGN_STATIC_PROP_OP: if (opline->op1_type == IS_CONST) { // op1 static property diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2ad3f6b323d8f..6aa6e75cdb23e 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2681,6 +2681,8 @@ static void zend_emit_return_type_check( opline->result_type = expr->op_type = IS_TMP_VAR; opline->result.var = expr->u.op.var = get_temporary_variable(); } + + opline->op2.num = zend_alloc_cache_slot(); } } /* }}} */ @@ -7725,6 +7727,11 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 SET_NODE(opline->result, &var_node); opline->op1.num = i + 1; + if (type_ast) { + /* Allocate cache slot for last successful type check */ + opline->extended_value = zend_alloc_cache_slot(); + } + uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0) | (is_promoted ? _ZEND_IS_PROMOTED_BIT : 0); ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 89fbcf2cbd781..563e12d3af238 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1141,10 +1141,13 @@ static bool zend_check_intersection_type_from_list( } static zend_always_inline bool zend_check_type_slow( - const zend_type *type, zval *arg, const zend_reference *ref, + const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, bool is_return_type, bool is_internal) { if (ZEND_TYPE_IS_COMPLEX(*type) && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { + // if (*cache_slot == Z_OBJCE_P(arg)) { + // return true; + // } zend_class_entry *ce; if (UNEXPECTED(ZEND_TYPE_HAS_LIST(*type))) { if (ZEND_TYPE_IS_INTERSECTION(*type)) { @@ -1154,6 +1157,7 @@ static zend_always_inline bool zend_check_type_slow( ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) { if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { if (zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg))) { + *cache_slot = (void *) Z_OBJCE_P(arg); return true; } } else { @@ -1161,6 +1165,7 @@ static zend_always_inline bool zend_check_type_slow( ce = zend_fetch_ce_from_type(list_type); /* Instance of a single type part of a union is sufficient to pass the type check */ if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) { + *cache_slot = (void *) Z_OBJCE_P(arg); return true; } } @@ -1171,9 +1176,10 @@ static zend_always_inline bool zend_check_type_slow( /* If we have a CE we check if it satisfies the type constraint, * otherwise it will check if a standard type satisfies it. */ if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) { + *cache_slot = (void *) Z_OBJCE_P(arg); return true; } - } + }; } const uint32_t type_mask = ZEND_TYPE_FULL_MASK(*type); @@ -1204,7 +1210,7 @@ static zend_always_inline bool zend_check_type_slow( } static zend_always_inline bool zend_check_type( - const zend_type *type, zval *arg, zend_class_entry *scope, + const zend_type *type, zval *arg, void **cache_slot, zend_class_entry *scope, bool is_return_type, bool is_internal) { const zend_reference *ref = NULL; @@ -1219,25 +1225,29 @@ static zend_always_inline bool zend_check_type( return 1; } - return zend_check_type_slow(type, arg, ref, is_return_type, is_internal); + return zend_check_type_slow(type, arg, ref, cache_slot, is_return_type, is_internal); } ZEND_API bool zend_check_user_type_slow( - const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type) + const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, bool is_return_type) { return zend_check_type_slow( - type, arg, ref, is_return_type, /* is_internal */ false); + type, arg, ref, cache_slot, is_return_type, /* is_internal */ false); } -static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg) +static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg, void **cache_slot) { const zend_arg_info *cur_arg_info; ZEND_ASSERT(arg_num <= zf->common.num_args); cur_arg_info = &zf->common.arg_info[arg_num-1]; + if (Z_TYPE_P(arg) == IS_OBJECT && *cache_slot == Z_OBJCE_P(arg)) { + return 1; + } + if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, zf->common.scope, 0, 0))) { + && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { zend_verify_arg_error(zf, cur_arg_info, arg_num, arg); return 0; } @@ -1246,10 +1256,10 @@ static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf } static zend_always_inline bool zend_verify_variadic_arg_type( - const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg) + const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot) { ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); - if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, zf->common.scope, 0, 0))) { + if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { zend_verify_arg_error(zf, arg_info, arg_num, arg); return 0; } @@ -1273,8 +1283,9 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ break; } + void *cache_slot = NULL; if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, fbc->common.scope, 0, /* is_internal */ 1))) { + && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, &cache_slot, fbc->common.scope, 0, /* is_internal */ 1))) { return 0; } arg++; @@ -1480,7 +1491,8 @@ ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *re return 1; } - if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, NULL, 1, /* is_internal */ 1))) { + void *cache_slot = NULL; + if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, &cache_slot, NULL, 1, /* is_internal */ 1))) { zend_verify_internal_return_error(zf, ret); return 0; } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 97ef66879db91..75c2d07e5e5cb 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -106,7 +106,7 @@ ZEND_API ZEND_COLD void zend_verify_never_error( const zend_function *zf); ZEND_API bool zend_verify_ref_array_assignable(zend_reference *ref); ZEND_API bool zend_check_user_type_slow( - const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type); + const zend_type *type, zval *arg, const zend_reference *ref, void **cache_slot, bool is_return_type); #if ZEND_DEBUG ZEND_API bool zend_internal_call_should_throw(const zend_function *fbc, zend_execute_data *call); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9317d1ff592f5..02960c6558bd7 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4423,7 +4423,7 @@ ZEND_VM_C_LABEL(fcall_end): ZEND_VM_CONTINUE(); } -ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED) +ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED|CACHE_SLOT) { if (OP1_TYPE == IS_UNUSED) { SAVE_OPLINE(); @@ -4465,6 +4465,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV } 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); @@ -4481,7 +4482,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -5670,7 +5671,7 @@ ZEND_VM_HELPER(zend_verify_recv_arg_type_helper, ANY, ANY, zval *op_1) USE_OPLINE SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } @@ -5708,7 +5709,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NO ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST) +ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT) { USE_OPLINE uint32_t arg_num; @@ -5748,7 +5749,7 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST) ZEND_VM_C_LABEL(recv_init_check_type): if ((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) { SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } @@ -5758,7 +5759,7 @@ ZEND_VM_C_LABEL(recv_init_check_type): ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED) +ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -5781,7 +5782,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED) if (ZEND_TYPE_IS_SET(arg_info->type)) { ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS); do { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) { + 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(); } @@ -5809,7 +5810,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED) if (ZEND_TYPE_IS_SET(arg_info->type)) { SEPARATE_ARRAY(params); ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, 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); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index f7bec6f7198c8..902e254ff2424 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2757,7 +2757,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_verify_recv_ USE_OPLINE SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } @@ -4190,7 +4190,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON recv_init_check_type: if ((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) { SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } @@ -4295,7 +4295,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND if (ZEND_TYPE_IS_SET(arg_info->type)) { ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS); do { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) { + 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(); } @@ -4323,7 +4323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND if (ZEND_TYPE_IS_SET(arg_info->type)) { SEPARATE_ARRAY(params); ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, 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); @@ -10869,6 +10869,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP } 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); @@ -10885,7 +10886,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -21605,6 +21606,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN } 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); @@ -21621,7 +21623,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -30084,6 +30086,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN } 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); @@ -30100,7 +30103,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -37877,6 +37880,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED } 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); @@ -37893,7 +37897,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } @@ -50677,6 +50681,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU } 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); @@ -50693,7 +50698,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU } SAVE_OPLINE(); - if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) { zend_verify_return_error(EX(func), retval_ptr); HANDLE_EXCEPTION(); } diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index d7d4d9e770b5b..fc49be82b2591 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -300,7 +300,7 @@ static uint32_t zend_vm_opcodes_flags[210] = { 0x01040310, 0x00000003, 0x00000110, - 0x00000310, + 0x00040310, 0x00001307, 0x00001301, 0x00001301, @@ -360,7 +360,7 @@ static uint32_t zend_vm_opcodes_flags[210] = { 0x00000007, 0x00040003, 0x09000007, - 0x00000103, + 0x0000a103, 0x00002003, 0x03000001, 0x00000005, @@ -400,7 +400,7 @@ static uint32_t zend_vm_opcodes_flags[210] = { 0x00000003, 0x00000020, 0x00003000, - 0x00000110, + 0x00040110, 0x00000000, 0x00000007, 0x00000105, diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index b20afffa47df0..177feea3afa6e 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1900,8 +1900,9 @@ static bool ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_arg_info *arg { zend_execute_data *execute_data = EG(current_execute_data); const zend_op *opline = EX(opline); + void **cache_slot = CACHE_ADDR(opline->extended_value); bool ret = zend_check_user_type_slow( - &arg_info->type, arg, /* ref */ NULL, /* is_return_type */ false); + &arg_info->type, arg, /* ref */ NULL, cache_slot, /* is_return_type */ false); if (UNEXPECTED(!ret)) { zend_verify_arg_error(EX(func), arg_info, opline->op1.num, arg); return 0; @@ -1909,7 +1910,7 @@ static bool ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_arg_info *arg return ret; } -static void ZEND_FASTCALL zend_jit_verify_return_slow(zval *arg, const zend_op_array *op_array, zend_arg_info *arg_info) +static void ZEND_FASTCALL zend_jit_verify_return_slow(zval *arg, const zend_op_array *op_array, zend_arg_info *arg_info, void **cache_slot) { if (Z_TYPE_P(arg) == IS_NULL) { ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); @@ -1918,7 +1919,7 @@ static void ZEND_FASTCALL zend_jit_verify_return_slow(zval *arg, const zend_op_a } } if (UNEXPECTED(!zend_check_user_type_slow( - &arg_info->type, arg, /* ref */ NULL, /* is_return_type */ true))) { + &arg_info->type, arg, /* ref */ NULL, cache_slot, /* is_return_type */ true))) { zend_verify_return_error((zend_function*)op_array, arg); } } diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 09bfadd9f1fb0..4d006c19d34e9 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -11031,10 +11031,11 @@ static bool zend_jit_verify_return_type(zend_jit_ctx *jit, const zend_op *opline ref = zend_jit_zval_check_undef(jit, ref, opline->op1.var, NULL, 1); } - ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_verify_return_slow), + ir_CALL_4(IR_VOID, ir_CONST_FC_FUNC(zend_jit_verify_return_slow), ref, ir_LOAD_A(jit_EX(func)), - ir_CONST_ADDR(arg_info)); + ir_CONST_ADDR(arg_info), + ir_ADD_OFFSET(ir_LOAD_A(jit_EX(run_time_cache)), opline->op2.num)); zend_jit_check_exception(jit);