Inside a thread or fiber, the size of the keyword splat could be much smaller
and still cause a crash.
I found this issue while optimizing method calling by reducing implicit
allocations. Given the following code:
deff(kw: ,**kws)endkw={kw: 1}f(**kw)
The f(**kw) call previously allocated two hashes callee side instead of a
single hash. This is because setup_parameters_complex would extract the
keywords from the keyword splat hash to the C stack, to attempt to mirror
the case when literal keywords are passed without a keyword splat. Then, make_rest_kw_hash would build a new hash based on the extracted keywords
that weren't used for literal keywords.
Switch the implementation so that if a keyword splat is passed, literal keywords
are deleted from the keyword splat hash (or a copy of the hash if the hash is
not mutable).
In addition to avoiding the crash, this new approach is much more
efficient in all cases. With the included benchmark:
Fix crash when passing large keyword splat to method accepting keywords and keyword splat
The following code previously caused a crash:
Inside a thread or fiber, the size of the keyword splat could be much smaller
and still cause a crash.
I found this issue while optimizing method calling by reducing implicit
allocations. Given the following code:
The
f(**kw)
call previously allocated two hashes callee side instead of asingle hash. This is because
setup_parameters_complex
would extract thekeywords from the keyword splat hash to the C stack, to attempt to mirror
the case when literal keywords are passed without a keyword splat. Then,
make_rest_kw_hash
would build a new hash based on the extracted keywordsthat weren't used for literal keywords.
Switch the implementation so that if a keyword splat is passed, literal keywords
are deleted from the keyword splat hash (or a copy of the hash if the hash is
not mutable).
In addition to avoiding the crash, this new approach is much more
efficient in all cases. With the included benchmark: