Jean Boussier 7142a3debb Optimize Hash.new(capacity:)
Since the dynamic AR-table refactoring, `Hash.new(capacity:)` no
longer allocate the ideal size for capacity `<= 8`, because the
capacity allocation happens in `#initialize`, hence after the
slot has been allocated.

To solve that, we have to define a custom `.new` method, so we can
parse the `capacity:` argument prior to the slot allocation, similar
to how it's done for `String`.

However defining a custom `new` disable the `opt_new` optimization,
so to counter-act that we have to add a special branch in `opt_new`
to handle hash specifically, and parse the `capacity:` argument without
having to allocate a keyword arguments hash.

|                    |compare-ruby|built-ruby|
|:-------------------|-----------:|---------:|
|new                 |     21.185M|   24.041M|
|                    |           -|     1.13x|
|new_8               |     10.419M|   19.930M|
|                    |           -|     1.91x|
|new_index_8         |     22.113k|   22.534k|
|                    |           -|     1.02x|
|new_capa_index_8    |     21.786k|   22.455k|
|                    |           -|     1.03x|
|to_h_8              |     21.510k|   20.655k|
|                    |       1.04x|         -|
|new_with_capa_1k    |     21.047k|   21.933k|
|                    |           -|     1.04x|
|new_with_capa_100k  |     209.952|   207.936|
|                    |       1.01x|         -|
2026-10-29 11:14:36 +01:00
..
2026-10-29 11:14:36 +01:00
…
…
…