Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
3191-Add-fast-lanes-for-2-and-2-on-nil-argument...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3191-Add-fast-lanes-for-2-and-2-on-nil-arguments.patch of Package erlang
From 8eeb95d479c61ad30aa70aef3f686f9107845b27 Mon Sep 17 00:00:00 2001 From: Michael Davis <mcarsondavis@gmail.com> Date: Mon, 26 Aug 2024 16:39:42 -0400 Subject: [PATCH] Add fast-lanes for '++'/2 and '--'/2 on nil arguments Currently appending an empty list to another list causes the left-hand side list to be fully copied. We can skip the append operation when the right-hand side is nil since it shouldn't change the left-hand side list. In this fast-lane we scan the list to determine if it is improper so that cases like `[1, 2 | 3] ++ []` behave the same as cases like `[1, 2 | 3] ++ [4]`: return a badarg error. This patch adds similar fast-lanes for '--'/2: we can return the first argument when either the first or second arguments are nil. --- erts/emulator/beam/erl_bif_lists.c | 56 +++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/erts/emulator/beam/erl_bif_lists.c b/erts/emulator/beam/erl_bif_lists.c index 5dcd53d613..10afb3adaa 100644 --- a/erts/emulator/beam/erl_bif_lists.c +++ b/erts/emulator/beam/erl_bif_lists.c @@ -56,6 +56,36 @@ static int append_ctx_bin_dtor(Binary *context_bin) { return 1; } +static int append_empty_rhs(Process *p, ErtsAppendContext *context) { + static const Sint ELEMENTS_PER_RED = 32; + Sint budget, count; + + budget = ELEMENTS_PER_RED * ERTS_BIF_REDS_LEFT(p); + +#ifdef DEBUG + budget = budget / 10 + 1; +#endif + + for (count = 0; count < budget && is_list(context->iterator); count++) { + context->iterator = CDR(list_val(context->iterator)); + } + + BUMP_REDS(p, count / ELEMENTS_PER_RED); + + if (is_list(context->iterator)) { + return 0; + } else if (is_nil(context->iterator)) { +#ifdef DEBUG + context->result_cdr = &context->rhs_original; +#endif + context->result = context->lhs_original; + + return 1; + } + + return -1; +} + static Eterm append_create_trap_state(Process *p, ErtsAppendContext *from_context) { ErtsAppendContext *to_context; @@ -203,6 +233,11 @@ static BIF_RETTYPE lists_append_onheap(Process *p, ErtsAppendContext *context) { } static int append_continue(Process *p, ErtsAppendContext *context) { + /* Fast-lane when the rhs is nil: return lhs. */ + if (is_nil(context->rhs_original)) { + return append_empty_rhs(p, context); + } + /* We build the result on the unused part of the heap if possible to save * us the trouble of having to figure out the list size. We fall back to * lists_append_alloc when we run out of space. */ @@ -906,7 +941,12 @@ static int subtract_continue(Process *p, ErtsSubtractContext *context) { return res; } - if (context->lhs_remaining <= SUBTRACT_LHS_THRESHOLD) { + /* If the lhs list is empty then there's nothing to do. + * Returning early will be taken care of in the `SUBTRACT_STAGE_LEN_RHS` + * stage after the rhs list has been scanned. */ + if (context->lhs_remaining > 0 && + context->lhs_remaining <= SUBTRACT_LHS_THRESHOLD && + is_list(context->rhs_original)) { return subtract_enter_naive_lhs(p, context); } @@ -926,6 +966,20 @@ static int subtract_continue(Process *p, ErtsSubtractContext *context) { return res; } + /* If the lhs list is empty then the subtraction must return nil. */ + if (context->lhs_remaining == 0) { + ASSERT(is_nil(context->lhs_original)); + context->result = NIL; + return 1; + } + /* If the rhs list is empty then the subtraction should return the + * lhs list unchanged. */ + if (context->rhs_remaining == 0) { + ASSERT(is_nil(context->rhs_original)); + context->result = context->lhs_original; + return 1; + } + /* We've walked through both lists fully now so we no longer need * to check for errors past this point. */ -- 2.43.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor