Bug 1401675 Comment 23 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

In terms of stack location allocation in the baseline compiler, I am not sure I see the difference between multiple-value results and the expression stack.  Both spill to the stack as needed, precisely because we don't know the frame size until the end, and both have the same stack discipline.  

I am going to give this a try: when entering a block with nargs > JoinRegisterCount, we decrement the stack pointer appropriately to reserve space for the extra values.  When returning nvals > JoinRegisterCount, write the extra values to the stack at the block's saved stack height; since we eagerly reserve space there's no shuffling needed.  In the block there are appropriate Stk entries for all block parameters (stack-spilled or no), as well as return values from a nested `end`.

For the call ABI -- I am not entirely sure about this but I would propose reserving space for nresults > ReturnRegCount before any spilled arguments, with stack return value N having a higher address than stack return value N+1.  The stack return area should be word-aligned, which is already the case for baseline frames AFAIU.  At return sites, appropriate Stk entries are present indicating the stack return values if any; I think it works out OK here so that no shuffling is needed.

As far as variable-sized data structures go.  AFAIU the important bit is the ExprType for return types for blocks and function calls, and in the future for block parameters.  I agree that creating a bunch of potentially-heap-allocated data structures would be a lose.  I would propose instead a stack of block result types, and block result types become an index-and-count into this stack.  Two u32s should be sufficient for references to result types.  The stack itself can be supplied by the caller (like `stk_`) if needed.  I'll try this refactor first to see if it's perf-neutral.
In terms of stack location allocation in the baseline compiler, I am not sure I see the difference between multiple-value results and the expression stack.  Both spill to the stack as needed, precisely because we don't know the frame size until the end, and both have the same stack discipline.  

I am going to give this a try: when entering a block with ~nargs~ nvals > JoinRegisterCount, we decrement the stack pointer appropriately to reserve space for the extra values.  When returning nvals > JoinRegisterCount, write the extra values to the stack at the block's saved stack height; since we eagerly reserve space there's no shuffling needed.  In the block there are appropriate Stk entries for all block parameters (stack-spilled or no), as well as return values from a nested `end`.

For the call ABI -- I am not entirely sure about this but I would propose reserving space for nresults > ReturnRegCount before any spilled arguments, with stack return value N having a higher address than stack return value N+1.  The stack return area should be word-aligned, which is already the case for baseline frames AFAIU.  At return sites, appropriate Stk entries are present indicating the stack return values if any; I think it works out OK here so that no shuffling is needed.

As far as variable-sized data structures go.  AFAIU the important bit is the ExprType for return types for blocks and function calls, and in the future for block parameters.  I agree that creating a bunch of potentially-heap-allocated data structures would be a lose.  I would propose instead a stack of block result types, and block result types become an index-and-count into this stack.  Two u32s should be sufficient for references to result types.  The stack itself can be supplied by the caller (like `stk_`) if needed.  I'll try this refactor first to see if it's perf-neutral.

Back to Bug 1401675 Comment 23