From 36891a677593c6b2cfcac29adae7cd26f21b754e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 2 Jun 2025 23:35:42 +0200 Subject: [PATCH] Move VM exception checks (#18730) Checking the non-exception path without arguments first, this avoids a redundant check in the case without arguments. The exception path may become more expensive, but we don't optimize for exception flow, rather we optimize for the happy flow. The other paths are unaffected. --- Zend/zend_vm_def.h | 8 ++++---- Zend/zend_vm_execute.h | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 95d9a44f80d..617e114dd05 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5962,16 +5962,16 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); if (constructor == NULL) { - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next * opcode is DO_FCALL in case EXT instructions are used. */ if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { ZEND_VM_NEXT_OPCODE_EX(1, 2); } + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index aa1c8e7e175..791e4b4e884 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -11046,16 +11046,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); if (constructor == NULL) { - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next * opcode is DO_FCALL in case EXT instructions are used. */ if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { ZEND_VM_NEXT_OPCODE_EX(1, 2); } + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, @@ -30594,16 +30594,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); if (constructor == NULL) { - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next * opcode is DO_FCALL in case EXT instructions are used. */ if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { ZEND_VM_NEXT_OPCODE_EX(1, 2); } + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, @@ -38059,16 +38059,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); if (constructor == NULL) { - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next * opcode is DO_FCALL in case EXT instructions are used. */ if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { ZEND_VM_NEXT_OPCODE_EX(1, 2); } + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,