diff options
author | Tyson Andre <tysonandre775@hotmail.com> | 2021-02-12 19:42:03 -0500 |
---|---|---|
committer | Tyson Andre <tysonandre775@hotmail.com> | 2021-02-13 09:34:48 -0500 |
commit | 8ffc20ace6c8a59b30aea53e2100aa26e4f1f3ee (patch) | |
tree | 2d1a5e510b68167be1ab86dd2ea48ad2bc59ac92 /Zend/zend_vm_execute.h | |
parent | f74a02d263aa332d995f78bd71878012952623b1 (diff) | |
download | php-git-8ffc20ace6c8a59b30aea53e2100aa26e4f1f3ee.tar.gz |
Optimize Traversable unpacking in zend_vm_def.h
The C compiler sees that a dynamic function is being called, so it cannot infer
that iter->funcs has not changed.
This results in more assembly instructions and slightly more time to execute that code
path.
Unpacking traversables to arrays(`ZEND_ADD_ARRAY_UNPACK`),
starting foreach loops (`ZEND_FE_FETCH*`), etc. are affected.
```
<?php
/*
* Before: 1.576 seconds
* After: 1.474 seconds
*/
function example() {
$start = hrtime(true);
$it = new SplFixedArray(1000);
$total = 0;
for ($i = 0; $i < 100000; $i++) {
$total += count([...$it]);
}
$end = hrtime(true);
printf("Elapsed: %.6f\n", ($end - $start) / 1_000_000_000);
}
example();
```
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r-- | Zend/zend_vm_execute.h | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0fe4fb5bb5..b170b9ab47 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2203,26 +2203,27 @@ send_again: HANDLE_EXCEPTION(); } - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); + const zend_object_iterator_funcs *funcs = iter->funcs; + if (funcs->rewind) { + funcs->rewind(iter); } - for (; iter->funcs->valid(iter) == SUCCESS; ++arg_num) { + for (; funcs->valid(iter) == SUCCESS; ++arg_num) { zval *arg, *top; if (UNEXPECTED(EG(exception) != NULL)) { break; } - arg = iter->funcs->get_current_data(iter); + arg = funcs->get_current_data(iter); if (UNEXPECTED(EG(exception) != NULL)) { break; } zend_string *name = NULL; - if (iter->funcs->get_current_key) { + if (funcs->get_current_key) { zval key; - iter->funcs->get_current_key(iter, &key); + funcs->get_current_key(iter, &key); if (UNEXPECTED(EG(exception) != NULL)) { break; } @@ -2284,7 +2285,7 @@ send_again: ZEND_CALL_NUM_ARGS(EX(call))++; } - iter->funcs->move_forward(iter); + funcs->move_forward(iter); } zend_iterator_dtor(iter); @@ -2544,25 +2545,26 @@ add_unpack_again: HANDLE_EXCEPTION(); } - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); + const zend_object_iterator_funcs *funcs = iter->funcs; + if (funcs->rewind) { + funcs->rewind(iter); } - for (; iter->funcs->valid(iter) == SUCCESS; ) { + for (; funcs->valid(iter) == SUCCESS; ) { zval *val; if (UNEXPECTED(EG(exception) != NULL)) { break; } - val = iter->funcs->get_current_data(iter); + val = funcs->get_current_data(iter); if (UNEXPECTED(EG(exception) != NULL)) { break; } zval key; - if (iter->funcs->get_current_key) { - iter->funcs->get_current_key(iter, &key); + if (funcs->get_current_key) { + funcs->get_current_key(iter, &key); if (UNEXPECTED(EG(exception) != NULL)) { break; } @@ -2592,7 +2594,7 @@ add_unpack_again: } } - iter->funcs->move_forward(iter); + funcs->move_forward(iter); if (UNEXPECTED(EG(exception))) { break; } @@ -21692,15 +21694,16 @@ fe_fetch_r_exit: } } } else { + const zend_object_iterator_funcs *funcs = iter->funcs; if (EXPECTED(++iter->index > 0)) { /* This could cause an endless loop if index becomes zero again. * In case that ever happens we need an additional flag. */ - iter->funcs->move_forward(iter); + funcs->move_forward(iter); if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); } - if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) { + if (UNEXPECTED(funcs->valid(iter) == FAILURE)) { /* reached end of iteration */ if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); @@ -21709,7 +21712,7 @@ fe_fetch_r_exit: goto fe_fetch_r_exit; } } - value = iter->funcs->get_current_data(iter); + value = funcs->get_current_data(iter); if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -21719,8 +21722,8 @@ fe_fetch_r_exit: goto fe_fetch_r_exit; } if (RETURN_VALUE_USED(opline)) { - if (iter->funcs->get_current_key) { - iter->funcs->get_current_key(iter, EX_VAR(opline->result.var)); + if (funcs->get_current_key) { + funcs->get_current_key(iter, EX_VAR(opline->result.var)); if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -21845,15 +21848,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z } } } else { + const zend_object_iterator_funcs *funcs = iter->funcs; if (++iter->index > 0) { /* This could cause an endless loop if index becomes zero again. * In case that ever happens we need an additional flag. */ - iter->funcs->move_forward(iter); + funcs->move_forward(iter); if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); } - if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) { + if (UNEXPECTED(funcs->valid(iter) == FAILURE)) { /* reached end of iteration */ if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); @@ -21862,7 +21866,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z goto fe_fetch_w_exit; } } - value = iter->funcs->get_current_data(iter); + value = funcs->get_current_data(iter); if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); @@ -21872,8 +21876,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z goto fe_fetch_w_exit; } if (RETURN_VALUE_USED(opline)) { - if (iter->funcs->get_current_key) { - iter->funcs->get_current_key(iter, EX_VAR(opline->result.var)); + if (funcs->get_current_key) { + funcs->get_current_key(iter, EX_VAR(opline->result.var)); if (UNEXPECTED(EG(exception) != NULL)) { UNDEF_RESULT(); HANDLE_EXCEPTION(); |