Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
3461-ets-Treat-keys-containing-maps-as-unbound....
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3461-ets-Treat-keys-containing-maps-as-unbound.patch of Package erlang
From eb7e92f0b42e9f6a6617962b00f9015e22cadadb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org> Date: Tue, 16 Apr 2024 15:27:39 +0200 Subject: [PATCH] ets: Treat keys containing maps as unbound Fixes #8385 --- erts/emulator/beam/erl_db_hash.c | 2 +- erts/emulator/beam/erl_db_tree.c | 2 +- erts/emulator/beam/erl_db_util.c | 29 ++++++++++------------------- erts/emulator/beam/erl_db_util.h | 2 +- lib/stdlib/test/ets_SUITE.erl | 16 +++++++++++++++- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index 6eb7bde1b4..a5e6167785 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -2943,7 +2943,7 @@ static int analyze_pattern(DbTableHash *tb, Eterm pattern, } else { key = db_getkey(tb->common.keypos, tpl); if (is_value(key)) { - if (!db_has_variable(key)) { /* Bound key */ + if (db_is_fully_bound(key)) { int ix, search_slot; HashDbTerm** bp; erts_rwmtx_t* lck; diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c index a439b974a7..8329764cf7 100644 --- a/erts/emulator/beam/erl_db_tree.c +++ b/erts/emulator/beam/erl_db_tree.c @@ -3749,7 +3749,7 @@ static enum ms_key_boundness key_boundness(DbTableCommon *tb, key = db_getkey(tb->keypos, pattern); if (is_non_value(key)) return MS_KEY_IMPOSSIBLE; /* can't possibly match anything */ - if (!db_has_variable(key)) { /* Bound key */ + if (db_is_fully_bound(key)) { *keyp = key; return MS_KEY_BOUND; } else if (key != am_Underscore && diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index 8bace68d0f..7488c5c893 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -3514,11 +3514,8 @@ int db_has_map(Eterm node) { return 0; } -/* check if obj is (or contains) a variable */ -/* return 1 if obj contains a variable or underscore */ -/* return 0 if obj is fully ground */ - -int db_has_variable(Eterm node) { +/* Check if obj is fully bound (contains no variables, underscores, or maps) */ +int db_is_fully_bound(Eterm node) { DECLARE_ESTACK(s); ESTACK_PUSH(s,node); @@ -3539,30 +3536,24 @@ int db_has_variable(Eterm node) { while(arity--) { ESTACK_PUSH(s,*(++tuple)); } - } else if (is_flatmap(node)) { - Eterm *values = flatmap_get_values(flatmap_val(node)); - Uint size = flatmap_get_size(flatmap_val(node)); - ESTACK_PUSH(s, ((flatmap_t *) flatmap_val(node))->keys); - while (size--) { - ESTACK_PUSH(s, *(values++)); - } - } else if (is_map(node)) { /* other map-nodes or map-heads */ - Eterm *ptr = hashmap_val(node); - int i = hashmap_bitcount(MAP_HEADER_VAL(*ptr)); - ptr += MAP_HEADER_ARITY(*ptr); - while(i--) { ESTACK_PUSH(s, *++ptr); } + } else if (is_map(node)) { + /* Like in Erlang code, "literal" maps in a pattern match any + * map that has the given elements, so they must be considered + * variable. */ + DESTROY_ESTACK(s); + return 0; } break; case TAG_PRIMARY_IMMED1: if (node == am_Underscore || db_is_variable(node) >= 0) { DESTROY_ESTACK(s); - return 1; + return 0; } break; } } DESTROY_ESTACK(s); - return 0; + return 1; } /* diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h index 6ed1e15104..eb129aadcd 100644 --- a/erts/emulator/beam/erl_db_util.h +++ b/erts/emulator/beam/erl_db_util.h @@ -450,7 +450,7 @@ void* db_store_term_comp(DbTableCommon *tb, /*May be NULL*/ Eterm db_copy_element_from_ets(DbTableCommon* tb, Process* p, DbTerm* obj, Uint pos, Eterm** hpp, Uint extra); int db_has_map(Eterm obj); -int db_has_variable(Eterm obj); +int db_is_fully_bound(Eterm obj); int db_is_variable(Eterm obj); void db_do_update_element(DbUpdateHandle* handle, Sint position, diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 588096301d..cd021e78af 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -106,6 +106,7 @@ -export([take/1]). -export([whereis_table/1]). -export([ms_excessive_nesting/1]). +-export([bound_maps/1]). -export([init_per_testcase/2, end_per_testcase/2]). %% Convenience for manual testing @@ -187,7 +188,9 @@ all() -> test_table_memory_concurrency, test_delete_table_while_size_snapshot, test_decentralized_counters_setting, - ms_excessive_nesting]. + ms_excessive_nesting, + bound_maps + ]. groups() -> @@ -8863,6 +8866,16 @@ test_terms(Test_Func, Mode) -> end, ok. +bound_maps(_Config) -> + T = ets:new('__bound_maps__', [ordered_set, public]), + Ref = make_ref(), + Attrs = [#{}, #{key => value}], + [ets:insert_new(T, {{Attr, Ref}, original}) || Attr <- Attrs], + Attr = #{}, + Key = {Attr, Ref}, + MS = [{{Key, '$1'},[],[{{{element, 1, '$_'}, {const, new}}}]}], + 2 = ets:select_replace(T, MS), + ok. id(I) -> I. -- 2.35.3
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