File 5811-erts-Optimize-maps-merge-2-further-with-heap-mutatio.patch of Package erlang
From 93d1dd208da2e974715ad55df0ba939c36e02ed0 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Fri, 17 Mar 2023 13:36:54 +0100
Subject: [PATCH] erts: Optimize maps:merge/2 further with heap mutation
If both maps have all the keys and 1st map have a literal key tuple
but 2nd map does not, then we mutate 2nd map with literal key tuple
before returning it.
---
erts/emulator/beam/erl_map.c | 10 ++++++++++
erts/emulator/test/map_SUITE.erl | 2 ++
2 files changed, 12 insertions(+)
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 47109ccc84..e7452f4e8c 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -1407,6 +1407,16 @@ static Eterm flatmap_merge(Process *p, Eterm map1, Eterm map2) {
if (n == n2) {
/* Reuse entire map2 */
+ if (n == n1
+ && erts_is_literal(mp1->keys, boxed_val(mp1->keys))
+ && !erts_is_literal(mp2->keys, boxed_val(mp2->keys))) {
+ /*
+ * We want map2, but map1 has a nice literal key tuple.
+ * Solution: MUTATE HEAP to get both.
+ */
+ ASSERT(eq(mp1->keys, mp2->keys));
+ mp2->keys = mp1->keys;
+ }
HRelease(p, hp, (Eterm *)mp_new);
return map2;
}
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 99e5e1af7d..030ad5ee13 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -2207,6 +2207,8 @@ t_bif_map_merge(Config) when is_list(Config) ->
false = erts_debug:same(erts_internal:map_to_tuple_keys(MS_c), MS_keys),
MS_cc = maps:merge(MS, MS_c),
true = erts_debug:same(MS_cc, MS_c),
+ %% not only do we reuse MS_c, it has mutated to use the literal keys of MS
+ true = erts_debug:same(erts_internal:map_to_tuple_keys(MS_c), MS_keys),
MS_d = maps:merge(MS_c, MS),
true = erts_debug:same(MS_d, MS),
--
2.35.3