summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/erl_db_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/erl_db_util.c')
-rw-r--r--erts/emulator/beam/erl_db_util.c107
1 files changed, 61 insertions, 46 deletions
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 8243ac1a73..a236a09791 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -898,8 +898,8 @@ static Eterm dmc_lookup_bif_reversed(void *f);
static int cmp_uint(void *a, void *b);
static int cmp_guard_bif(void *a, void *b);
static int match_compact(ErlHeapFragment *expr, DMCErrInfo *err_info);
-static Uint my_size_object(Eterm t);
-static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap);
+static Uint my_size_object(Eterm t, int is_hashmap_node);
+static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap, int);
/* Guard subroutines */
static void
@@ -3879,11 +3879,11 @@ static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(UWord) *text,
if (is_immed(t)) {
tmp = t;
} else {
- sz = my_size_object(t);
+ sz = my_size_object(t, 0);
if (sz) {
emb = new_message_buffer(sz);
hp = emb->mem;
- tmp = my_copy_struct(t,&hp,&(emb->off_heap));
+ tmp = my_copy_struct(t,&hp,&(emb->off_heap), 0);
emb->next = context->save;
context->save = emb;
}
@@ -5368,33 +5368,39 @@ static int match_compact(ErlHeapFragment *expr, DMCErrInfo *err_info)
/*
** Simple size object that takes care of function calls and constant tuples
*/
-static Uint my_size_object(Eterm t)
+static Uint my_size_object(Eterm t, int is_hashmap_node)
{
Uint sum = 0;
- Eterm tmp;
Eterm *p;
switch (t & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_LIST:
- sum += 2 + my_size_object(CAR(list_val(t))) +
- my_size_object(CDR(list_val(t)));
+ sum += 2 + my_size_object(CAR(list_val(t)), 0) +
+ my_size_object(CDR(list_val(t)), 0);
break;
case TAG_PRIMARY_BOXED:
if (is_tuple(t)) {
- if (tuple_val(t)[0] == make_arityval(1) && is_tuple(tmp = tuple_val(t)[1])) {
- Uint i,n;
- p = tuple_val(tmp);
- n = arityval(p[0]);
- sum += 1 + n;
- for (i = 1; i <= n; ++i)
- sum += my_size_object(p[i]);
- } else if (tuple_val(t)[0] == make_arityval(2) &&
- is_atom(tmp = tuple_val(t)[1]) &&
- tmp == am_const) {
+ Eterm* tpl = tuple_val(t);
+ Uint i,n;
+
+ if (is_hashmap_node) {
+ /* hashmap collision node, no matchspec syntax here */
+ }
+ else if (tpl[0] == make_arityval(1) && is_tuple(tpl[1])) {
+ tpl = tuple_val(tpl[1]);
+ }
+ else if (tpl[0] == make_arityval(2) && tpl[1] == am_const) {
sum += size_object(tuple_val(t)[2]);
- } else {
+ break;
+ }
+ else {
erts_exit(ERTS_ERROR_EXIT,"Internal error, sizing unrecognized object in "
"(d)ets:match compilation.");
}
+
+ n = arityval(tpl[0]);
+ sum += 1 + n;
+ for (i = 1; i <= n; ++i)
+ sum += my_size_object(tpl[i], 0);
break;
} else if (is_map(t)) {
if (is_flatmap(t)) {
@@ -5407,7 +5413,7 @@ static Uint my_size_object(Eterm t)
n = arityval(p[0]);
sum += 1 + n;
for (int i = 1; i <= n; ++i)
- sum += my_size_object(p[i]);
+ sum += my_size_object(p[i], 0);
/* Calculate size of values */
p = (Eterm *)mp;
@@ -5415,18 +5421,19 @@ static Uint my_size_object(Eterm t)
sum += n + 3;
p += 3; /* hdr + size + keys words */
while (n--) {
- sum += my_size_object(*p++);
+ sum += my_size_object(*p++, 0);
}
} else {
Eterm *head = (Eterm *)hashmap_val(t);
Eterm hdr = *head;
Uint sz;
+
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
sum += 1 + sz + header_arity(hdr);
head += 1 + header_arity(hdr);
while(sz-- > 0) {
- sum += my_size_object(head[sz]);
+ sum += my_size_object(head[sz], 1);
}
}
break;
@@ -5439,46 +5446,54 @@ static Uint my_size_object(Eterm t)
return sum;
}
-static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
+static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap,
+ int is_hashmap_node)
{
Eterm ret = NIL, a, b;
Eterm *p;
Uint sz;
switch (t & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_LIST:
- a = my_copy_struct(CAR(list_val(t)), hp, off_heap);
- b = my_copy_struct(CDR(list_val(t)), hp, off_heap);
+ a = my_copy_struct(CAR(list_val(t)), hp, off_heap, 0);
+ b = my_copy_struct(CDR(list_val(t)), hp, off_heap, 0);
ret = CONS(*hp, a, b);
*hp += 2;
break;
case TAG_PRIMARY_BOXED:
if (is_tuple(t)) {
- if (tuple_val(t)[0] == make_arityval(1) &&
- is_tuple(a = tuple_val(t)[1])) {
- Uint i,n;
- p = tuple_val(a);
- n = arityval(p[0]);
- if (n == 0) {
- ret = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
- } else {
- Eterm *savep = *hp;
- ret = make_tuple(savep);
- *hp += n + 1;
- *savep++ = make_arityval(n);
- for(i = 1; i <= n; ++i)
- *savep++ = my_copy_struct(p[i], hp, off_heap);
- }
+ Eterm* tpl = tuple_val(t);
+ Uint i,n;
+ Eterm *savep;
+
+ if (is_hashmap_node) {
+ /* hashmap collision node, no matchspec syntax here */
+ }
+ else if (tpl[0] == make_arityval(1) && is_tuple(tpl[1])) {
+ /* A {{...}} expression */
+ tpl = tuple_val(tpl[1]);
}
- else if (tuple_val(t)[0] == make_arityval(2) &&
- tuple_val(t)[1] == am_const) {
+ else if (tpl[0] == make_arityval(2) && tpl[1] == am_const) {
/* A {const, XXX} expression */
- b = tuple_val(t)[2];
+ b = tpl[2];
sz = size_object(b);
ret = copy_struct(b,sz,hp,off_heap);
+ break;
} else {
erts_exit(ERTS_ERROR_EXIT, "Trying to constant-copy non constant expression "
"0x%bex in (d)ets:match compilation.", t);
}
+ n = arityval(tpl[0]);
+ if (n == 0) {
+ ret = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ savep = *hp;
+ ret = make_tuple(savep);
+ *hp += n + 1;
+ *savep++ = tpl[0];
+ for(i = 1; i <= n; ++i)
+ *savep++ = my_copy_struct(tpl[i], hp, off_heap, 0);
+ }
+
} else if (is_map(t)) {
if (is_flatmap(t)) {
Uint i,n;
@@ -5499,7 +5514,7 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
*hp += n + 1;
*savep++ = make_arityval(n);
for(i = 1; i <= n; ++i)
- *savep++ = my_copy_struct(p[i], hp, off_heap);
+ *savep++ = my_copy_struct(p[i], hp, off_heap, 0);
}
savep = *hp;
ret = make_flatmap(savep);
@@ -5511,7 +5526,7 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
*savep++ = keys;
p += 3; /* hdr + size + keys words */
for (i = 0; i < n; i++)
- *savep++ = my_copy_struct(p[i], hp, off_heap);
+ *savep++ = my_copy_struct(p[i], hp, off_heap, 0);
erts_usort_flatmap((flatmap_t*)flatmap_val(ret));
} else {
Eterm *head = hashmap_val(t);
@@ -5528,7 +5543,7 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
*savep++ = *head++; /* map size */
for (int i = 0; i < sz; i++) {
- *savep++ = my_copy_struct(head[i],hp,off_heap);
+ *savep++ = my_copy_struct(head[i],hp,off_heap, 1);
}
}
} else {