diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d71c06c0a13..3c3065e1568 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -9720,7 +9720,11 @@ ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED, NUM|CACHE_SLOT) if (closure) { ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); } else { - zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), (zend_ulong)(uintptr_t)call->func); + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { zend_closure_from_frame(closure_zv, call); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 50b65c864ed..50870ce463d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -39093,7 +39093,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONV if (closure) { ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); } else { - zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), (zend_ulong)(uintptr_t)call->func); + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { zend_closure_from_frame(closure_zv, call); } @@ -94331,7 +94335,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_S if (closure) { ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); } else { - zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), (zend_ulong)(uintptr_t)call->func); + /* Rotate the key for better hash distribution. */ + const int shift = sizeof(size_t) == 4 ? 6 : 7; + zend_ulong key = (zend_ulong)(uintptr_t)call->func; + key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); + zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { zend_closure_from_frame(closure_zv, call); }