From 393774feae702c79f0387c9694abdd63ffcc2450 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 8 Apr 2023 15:59:07 +0200 Subject: [PATCH] Move EG(exception) check outside the loop for unpacking Right now there's an EG(exception) check inside the loop for the iterator object. As far as I know, funcs->valid(iter) will return FAILURE when an exception is set instead of success. That means that the exception check was not put there for funcs->valid. But it could be for funcs->rewind(iter), because if I look at other callers it looks like other callers do check for an exception after calling that function. Move it outside the loop and inside the funcs->rewind case for better performance. I think this is also more correct because funcs->valid(iter) probably shouldn't be called if the rewinding failed. --- Zend/zend_vm_def.h | 8 ++++---- Zend/zend_vm_execute.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 88b46a641d079..56435e2080683 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5186,15 +5186,14 @@ ZEND_VM_C_LABEL(send_again): const zend_object_iterator_funcs *funcs = iter->funcs; if (funcs->rewind) { funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + ZEND_VM_C_GOTO(after_loop); + } } for (; funcs->valid(iter) == SUCCESS; ++arg_num) { zval *arg, *top; - if (UNEXPECTED(EG(exception) != NULL)) { - break; - } - arg = funcs->get_current_data(iter); if (UNEXPECTED(EG(exception) != NULL)) { break; @@ -5277,6 +5276,7 @@ ZEND_VM_C_LABEL(send_again): funcs->move_forward(iter); } +ZEND_VM_C_LABEL(after_loop): zend_iterator_dtor(iter); } } else if (EXPECTED(Z_ISREF_P(args))) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d44be7760c43a..ef6578145af0e 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2324,15 +2324,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_ const zend_object_iterator_funcs *funcs = iter->funcs; if (funcs->rewind) { funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + goto after_loop; + } } for (; funcs->valid(iter) == SUCCESS; ++arg_num) { zval *arg, *top; - if (UNEXPECTED(EG(exception) != NULL)) { - break; - } - arg = funcs->get_current_data(iter); if (UNEXPECTED(EG(exception) != NULL)) { break; @@ -2415,6 +2414,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_ funcs->move_forward(iter); } +after_loop: zend_iterator_dtor(iter); } } else if (EXPECTED(Z_ISREF_P(args))) {