diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index db973572aca3a..ce9b072aa39c9 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -508,11 +508,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx case ZEND_RECV: case ZEND_RECV_VARIADIC: { - size_t num_classes = type_num_classes(op_array, opline->op1.num); - if (num_classes) { - opline->extended_value = cache_size; - cache_size += num_classes * sizeof(void *); - } + size_t num_classes = 1 + type_num_classes(op_array, opline->op1.num); + opline->extended_value = cache_size; + cache_size += num_classes * sizeof(void *); break; } case ZEND_VERIFY_RETURN_TYPE: diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2e405de30ea62..e398fa060cec4 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7757,7 +7757,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 if (type_ast) { /* Allocate cache slot to speed-up run-time class resolution */ opline->extended_value = - zend_alloc_cache_slots(zend_type_get_num_classes(arg_info->type)); + zend_alloc_cache_slots(1 + zend_type_get_num_classes(arg_info->type)); } uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 162b7e84cefbe..919f80585f43a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5671,10 +5671,14 @@ 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, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value) + 1))) { HANDLE_EXCEPTION(); } + if (EXPECTED(Z_TYPE_P(op_1) == IS_OBJECT)) { + CACHE_PTR(opline->extended_value, Z_OBJCE_P(op_1)); + } + ZEND_VM_NEXT_OPCODE(); } @@ -5690,7 +5694,9 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED, CACHE_SLOT) param = EX_VAR(opline->result.var); - if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param))))) { + if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param)))) + && !(EXPECTED(Z_TYPE_P(param) == IS_OBJECT) + && CACHED_PTR(opline->extended_value) == Z_OBJCE_P(param))) { ZEND_VM_DISPATCH_TO_HELPER(zend_verify_recv_arg_type_helper, op_1, param); } @@ -5749,7 +5755,7 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT) 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, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value) + 1))) { HANDLE_EXCEPTION(); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 902e254ff2424..aef1d087a506e 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2757,10 +2757,14 @@ 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, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value) + 1))) { HANDLE_EXCEPTION(); } + if (EXPECTED(Z_TYPE_P(op_1) == IS_OBJECT)) { + CACHE_PTR(opline->extended_value, Z_OBJCE_P(op_1)); + } + ZEND_VM_NEXT_OPCODE(); } @@ -4190,7 +4194,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, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value) + 1))) { HANDLE_EXCEPTION(); } } @@ -4265,7 +4269,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_H param = EX_VAR(opline->result.var); - if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param))))) { + if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param)))) + && !(EXPECTED(Z_TYPE_P(param) == IS_OBJECT) + && CACHED_PTR(opline->extended_value) == Z_OBJCE_P(param))) { ZEND_VM_TAIL_CALL(zend_verify_recv_arg_type_helper_SPEC(param ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 177feea3afa6e..3d9ac56d139dc 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1902,7 +1902,7 @@ static bool ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_arg_info *arg 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, cache_slot, /* is_return_type */ false); + &arg_info->type, arg, /* ref */ NULL, cache_slot + 1, /* is_return_type */ false); if (UNEXPECTED(!ret)) { zend_verify_arg_error(EX(func), arg_info, opline->op1.num, arg); return 0;