Skip to content
  • Jeremy Evans's avatar
    ea7ceff8
    Avoid hash allocation for certain proc calls · ea7ceff8
    Jeremy Evans authored
    Previously, proc calls such as:
    
    ```ruby
    proc{|| }.(**empty_hash)
    proc{|b: 1| }.(**r2k_array_with_empty_hash)
    ```
    
    both allocated hashes unnecessarily, due to two separate code paths.
    
    The first call goes through CALLER_SETUP_ARG/vm_caller_setup_keyword_hash,
    and is simple to fix by not duping an empty keyword hash that will be
    dropped.
    
    The second case is more involved, in setup_parameters_complex, but is
    fixed the exact same way as when the ruby2_keywords hash is not empty,
    by flattening the rest array to the VM stack, ignoring the last
    element (the empty keyword splat).  Add a flatten_rest_array static
    function to handle this case.
    
    Update test_allocation.rb to automatically convert the method call
    allocation tests to proc allocation tests, at least for the calls
    that can be converted.  With the code changes, all proc call
    allocation tests pass, showing that proc calls and method calls
    now allocate the same number of objects.
    
    I've audited the allocation tests, and I believe that all of the low
    hanging fruit has been collected.  All remaining allocations are
    either caller side:
    
    * Positional splat + post argument
    * Multiple positional splats
    * Literal keywords + keyword splat
    * Multiple keyword splats
    
    Or callee side:
    
    * Positional splat parameter
    * Keyword splat parameter
    * Keyword to positional argument conversion for methods that don't accept keywords
    * ruby2_keywords method called with keywords
    
    Reapplies abc04e89, which was reverted at
    d56470a2, with the addition of a bug fix and
    test.
    
    Fixes [Bug #20679]
    ea7ceff8
    Avoid hash allocation for certain proc calls
    Jeremy Evans authored
    Previously, proc calls such as:
    
    ```ruby
    proc{|| }.(**empty_hash)
    proc{|b: 1| }.(**r2k_array_with_empty_hash)
    ```
    
    both allocated hashes unnecessarily, due to two separate code paths.
    
    The first call goes through CALLER_SETUP_ARG/vm_caller_setup_keyword_hash,
    and is simple to fix by not duping an empty keyword hash that will be
    dropped.
    
    The second case is more involved, in setup_parameters_complex, but is
    fixed the exact same way as when the ruby2_keywords hash is not empty,
    by flattening the rest array to the VM stack, ignoring the last
    element (the empty keyword splat).  Add a flatten_rest_array static
    function to handle this case.
    
    Update test_allocation.rb to automatically convert the method call
    allocation tests to proc allocation tests, at least for the calls
    that can be converted.  With the code changes, all proc call
    allocation tests pass, showing that proc calls and method calls
    now allocate the same number of objects.
    
    I've audited the allocation tests, and I believe that all of the low
    hanging fruit has been collected.  All remaining allocations are
    either caller side:
    
    * Positional splat + post argument
    * Multiple positional splats
    * Literal keywords + keyword splat
    * Multiple keyword splats
    
    Or callee side:
    
    * Positional splat parameter
    * Keyword splat parameter
    * Keyword to positional argument conversion for methods that don't accept keywords
    * ruby2_keywords method called with keywords
    
    Reapplies abc04e89, which was reverted at
    d56470a2, with the addition of a bug fix and
    test.
    
    Fixes [Bug #20679]
Loading