diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 68449b9ef050..350234c47f07 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -9719,7 +9719,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 0090bf77dd30..164fcfb3a98b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -39092,7 +39092,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); } @@ -94329,7 +94333,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); }