From 651c99b7aac8ac7ca7f84efa0d3bd3b541d6f3a4 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 15 Dec 2010 17:20:46 +0100 Subject: HALFWORD ETS Real matching on relative terms --- erts/emulator/beam/erl_db.c | 2 +- erts/emulator/beam/erl_db_hash.c | 2 +- erts/emulator/beam/erl_db_util.c | 81 +++++++++++++++++++++++----------------- erts/emulator/beam/erl_db_util.h | 7 ++-- erts/emulator/beam/global.h | 8 ++-- erts/emulator/beam/sys.h | 2 + erts/emulator/beam/utils.c | 40 ++++++++++---------- 7 files changed, 78 insertions(+), 64 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index f045690060..914eedce0c 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -2738,7 +2738,7 @@ BIF_RETTYPE ets_match_spec_run_r_3(BIF_ALIST_3) BIF_TRAP3(bif_export[BIF_ets_match_spec_run_r_3], BIF_P,lst,BIF_ARG_2,ret); } - res = db_prog_match(BIF_P, mp, CAR(list_val(lst)), NULL, 0, &dummy); + res = db_prog_match(BIF_P, mp, CAR(list_val(lst)), NULL, NULL, 0, &dummy); if (is_value(res)) { sz = size_object(res); hp = HAlloc(BIF_P, sz + 2); diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index ced6629c43..e43e734b27 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -429,7 +429,7 @@ static ERTS_INLINE void try_shrink(DbTableHash* tb) } #define EQ_REL(x,y,y_base) \ - (is_same(x,NULL,y,y_base) || (is_not_both_immed((x),(y)) && eq_rel((x),(y),y_base))) + (is_same(x,NULL,y,y_base) || (is_not_both_immed((x),(y)) && eq_rel((x),NULL,(y),y_base))) /* Is this a live object (not pseodo-deleted) with the specified key? */ diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index cff208ffa7..be8e10e8f2 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -1169,7 +1169,7 @@ Eterm erts_match_set_run(Process *p, Binary *mpsp, Eterm ret; ret = db_prog_match(p, mpsp, - NIL, args, + NIL, NULL, args, num_args, return_flags); #if defined(HARDDEBUG) if (is_non_value(ret)) { @@ -1194,9 +1194,7 @@ static Eterm erts_match_set_run_ets(Process *p, Binary *mpsp, { Eterm ret; - ret = db_prog_match(p, mpsp, - args, NULL, - num_args, return_flags); + ret = db_prog_match(p, mpsp, args, NULL, NULL, num_args, return_flags); #if defined(HARDDEBUG) if (is_non_value(ret)) { erts_fprintf(stderr, "Failed\n"); @@ -1596,7 +1594,8 @@ static Eterm dpm_array_to_list(Process *psp, Eterm *arr, int arity) ** the parameter 'arity' is only used if 'term' is actually an array, ** i.e. 'DCOMP_TRACE' was specified */ -Eterm db_prog_match(Process *c_p, Binary *bprog, Eterm term, +Eterm db_prog_match(Process *c_p, Binary *bprog, + Eterm term, Eterm* base, Eterm *termp, int arity, Uint32 *return_flags) @@ -1623,7 +1622,9 @@ Eterm db_prog_match(Process *c_p, Binary *bprog, Eterm term, Eterm (*bif)(Process*, ...); int fail_label; int atomic_trace; - Eterm* base = is_immed(term) ? NULL : termp; +#if HALFWORD_HEAP + int is_abs_variables = (base == NULL); +#endif #ifdef DMC_DEBUG Uint *heap_fence; Uint *eheap_fence; @@ -1631,8 +1632,6 @@ Eterm db_prog_match(Process *c_p, Binary *bprog, Eterm term, Uint save_op; #endif /* DMC_DEBUG */ - ASSERT(base==NULL); // SVERK: base not used for now, maybe remove - mpsp = get_match_pseudo_process(c_p, prog->heap_size); psp = &mpsp->process; @@ -1693,6 +1692,12 @@ restart: do_catch = 0; fail_label = -1; +#if HALFWORD_HEAP /* clear all variables for matchPushV */ + for (i=prog->eheap_offset-(1+FENCE_PATTERN_SIZE); i>=0; i--) { + hp[i] = NIL; + } +#endif + for (;;) { #ifdef DMC_DEBUG if (*heap_fence != FENCE_PATTERN) { @@ -1761,18 +1766,20 @@ restart: ep = *(--sp); break; case matchBind: + ASSERT_HALFWORD(is_abs_variables == !base); n = *pc++; hp[n] = *ep++; break; case matchCmp: + ASSERT_HALFWORD(is_abs_variables == !base); n = *pc++; - if (!eq_rel(hp[n],*ep,base)) + if (!eq_rel(hp[n],base,*ep,base)) FAIL(); ++ep; break; case matchEqBin: t = (Eterm) *pc++; - if (!eq_rel(t,*ep,base)) + if (!eq_rel(t,NULL,*ep,base)) FAIL(); ++ep; break; @@ -1787,7 +1794,7 @@ restart: case matchEqRef: if (!is_ref_rel(*ep,base)) FAIL(); - if (!eq_rel(make_internal_ref((Uint *) pc), *ep, base)) + if (!eq_rel(make_internal_ref((Uint *) pc), NULL, *ep, base)) FAIL(); i = thing_arityval(*((Uint *) pc)); pc += TermWords(i+1); @@ -1894,11 +1901,31 @@ restart: esp[-1] = t; break; case matchPushV: - *esp++ = hp[*pc++]; + n = *pc++; + #if HALFWORD_HEAP + if (!is_abs_variables && !is_immed(hp[n])) { + for (i=prog->eheap_offset-1; i>=0; i--) if (!is_immed(hp[i])) { + Uint sz = size_object_rel(hp[i], base); + Eterm* top = HAlloc(psp, sz); + hp[i] = copy_struct_rel(hp[i], sz, &top, &MSO(psp), base, NULL); + } + is_abs_variables = 1; + } + #endif + *esp++ = hp[n]; break; case matchPushExpr: ASSERT(is_tuple_rel(term,base)); - *esp++ = make_tuple(tuple_val_rel(term,base)); + #if HALFWORD_HEAP + if (base) { + Uint sz = size_object_rel(term, base); + Eterm* top = HAlloc(psp, sz); + *esp++ = copy_shallow_rel(tuple_val_rel(term,base), sz, + &top, &MSO(psp), base); + break; + } + #endif + *esp++ = term; break; case matchPushArrayAsList: n = arity; /* Only happens when 'term' is an array */ @@ -4883,35 +4910,22 @@ Eterm db_prog_match_and_copy(DbTableCommon* tb, Process* c_p, Binary* bprog, int all, DbTerm* obj, Eterm** hpp, Uint extra) { Uint32 dummy; + Eterm* base; Eterm res; if (tb->compress) { obj = db_alloc_tmp_uncompressed(tb, obj); + base = NULL; } -#if HALFWORD_HEAP - else { // SVERK: Heavy solution; make tmp copy - ErlOffHeap tmp_offheap; - Eterm* hp; - DbTerm* tmp = erts_alloc(ERTS_ALC_T_TMP, - sizeof(DbTerm) + obj->size*sizeof(Eterm)); - hp = tmp->tpl; - tmp_offheap.first = NULL; - copy_shallow_rel(obj->tpl, obj->size, &hp, &tmp_offheap, obj->tpl); - tmp->size = obj->size; - tmp->first_oh = tmp_offheap.first; - #ifdef DEBUG_CLONE - tmp->debug_clone = NULL; - #endif - obj = tmp; - } -#endif + else base = obj->tpl; - res = db_prog_match(c_p, bprog, make_tuple(obj->tpl), NULL, 0, &dummy); + res = db_prog_match(c_p, bprog, make_tuple_rel(obj->tpl,base), base, + NULL, 0, &dummy); if (is_value(res) && hpp!=NULL) { if (all) { *hpp = HAlloc(c_p, obj->size + extra); - res = copy_shallow(obj->tpl, obj->size, hpp, &MSO(c_p)); + res = copy_shallow_rel(obj->tpl, obj->size, hpp, &MSO(c_p), base); } else { Uint sz = size_object(res); @@ -4923,9 +4937,6 @@ Eterm db_prog_match_and_copy(DbTableCommon* tb, Process* c_p, Binary* bprog, if (tb->compress) { db_free_tmp_uncompressed(obj); } -#if HALFWORD_HEAP - else db_free_tmp_uncompressed(obj); // SVERK misleading name -#endif return res; } diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h index 600110e745..30b3eb731d 100644 --- a/erts/emulator/beam/erl_db_util.h +++ b/erts/emulator/beam/erl_db_util.h @@ -286,7 +286,7 @@ ERTS_GLB_INLINE Eterm db_copy_key(Process* p, DbTable* tb, DbTerm* obj) Uint size = size_object_rel(key, obj->tpl); Eterm* hp = HAlloc(p, size); Eterm res = copy_struct_rel(key, size, &hp, &MSO(p), obj->tpl, NULL); - ASSERT(eq_rel(res,key,obj->tpl)); + ASSERT(eq_rel(res,NULL,key,obj->tpl)); return res; } } @@ -305,7 +305,7 @@ ERTS_GLB_INLINE Eterm db_copy_object_from_ets(DbTableCommon* tb, DbTerm* bp, ERTS_GLB_INLINE int db_eq(DbTableCommon* tb, Eterm a, DbTerm* b) { if (!tb->compress) { - return eq_rel(a, make_tuple_rel(b->tpl,b->tpl), b->tpl); + return eq_rel(a, NULL, make_tuple_rel(b->tpl,b->tpl), b->tpl); } else { return db_eq_comp(tb, a, b); @@ -427,7 +427,8 @@ Binary *db_match_compile(Eterm *matchexpr, Eterm *guards, Eterm db_prog_match_and_copy(DbTableCommon* tb, Process* c_p, Binary* bprog, int all, DbTerm* obj, Eterm** hpp, Uint extra); /* Returns newly allocated MatchProg binary with refc == 0*/ -Eterm db_prog_match(Process *p, Binary *prog, Eterm term, Eterm *termp, int arity, +Eterm db_prog_match(Process *p, Binary *prog, Eterm term, Eterm* base, + Eterm *termp, int arity, Uint32 *return_flags /* Zeroed on enter */); /* returns DB_ERROR_NONE if matches, 1 if not matches and some db error on error. */ diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 1516d08299..b59f26b2bf 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -901,7 +901,7 @@ Eterm copy_struct_rel(Eterm, Uint, Eterm**, ErlOffHeap*, Eterm* src_base, Eterm* Eterm copy_shallow_rel(Eterm*, Uint, Eterm**, ErlOffHeap*, Eterm* src_base); # define copy_shallow(A,B,C,D) copy_shallow_rel(A,B,C,D,NULL) -#else /* HALFWORD_HEAP */ +#else /* !HALFWORD_HEAP */ Uint size_object(Eterm); # define size_object_rel(A,B) size_object(A) @@ -1506,11 +1506,11 @@ erts_dsprintf_buf_t *erts_create_tmp_dsbuf(Uint); void erts_destroy_tmp_dsbuf(erts_dsprintf_buf_t *); #if HALFWORD_HEAP -int eq_rel(Eterm a, Eterm b, Eterm* b_base); -# define eq(A,B) eq_rel(A,B,NULL) +int eq_rel(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base); +# define eq(A,B) eq_rel(A,NULL,B,NULL) #else int eq(Eterm, Eterm); -# define eq_rel(A,B,B_BASE) eq(A,B) +# define eq_rel(A,A_BASE,B,B_BASE) eq(A,B) #endif #define EQ(x,y) (((x) == (y)) || (is_not_both_immed((x),(y)) && eq((x),(y)))) diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index dff2dc37a2..e36f7cf8cf 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -229,9 +229,11 @@ int real_printf(const char *fmt, ...); # ifdef HALFWORD_HEAP_EMULATOR # define HALFWORD_HEAP 1 # define HALFWORD_ASSERT 0 +# define ASSERT_HALFWORD(COND) ASSERT(COND) # else # define HALFWORD_HEAP 0 # define HALFWORD_ASSERT 0 +# define ASSERT_HALFWORD(COND) # endif #endif diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 9cdd46f27a..2d0155bdf5 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -1901,7 +1901,7 @@ erts_destroy_tmp_dsbuf(erts_dsprintf_buf_t *dsbufp) * Returns 0 if not equal, or a non-zero value otherwise. */ #if HALFWORD_HEAP -int eq_rel(Eterm a, Eterm b, Eterm* b_base) +int eq_rel(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base) #else int eq(Eterm a, Eterm b) #endif @@ -1909,21 +1909,21 @@ int eq(Eterm a, Eterm b) DECLARE_WSTACK(stack); Sint sz; Eterm* aa; - Eterm* bb; + Eterm* bb; tailrecur: - if (is_same(a,NULL, b,b_base)) goto pop_next; + if (is_same(a, a_base, b, b_base)) goto pop_next; tailrecur_ne: switch (primary_tag(a)) { case TAG_PRIMARY_LIST: if (is_list(b)) { - Eterm* aval = list_val(a); + Eterm* aval = list_val_rel(a, a_base); Eterm* bval = list_val_rel(b, b_base); while (1) { Eterm atmp = CAR(aval); Eterm btmp = CAR(bval); - if (!is_same(atmp,NULL,btmp,b_base)) { + if (!is_same(atmp,a_base,btmp,b_base)) { WSTACK_PUSH2(stack,(UWord) CDR(bval),(UWord) CDR(aval)); a = atmp; b = btmp; @@ -1931,7 +1931,7 @@ tailrecur_ne: } atmp = CDR(aval); btmp = CDR(bval); - if (is_same(atmp,NULL,btmp,b_base)) { + if (is_same(atmp,a_base,btmp,b_base)) { goto pop_next; } if (is_not_list(atmp) || is_not_list(btmp)) { @@ -1939,7 +1939,7 @@ tailrecur_ne: b = btmp; goto tailrecur_ne; } - aval = list_val(atmp); + aval = list_val_rel(atmp, a_base); bval = list_val_rel(btmp, b_base); } } @@ -1947,11 +1947,11 @@ tailrecur_ne: case TAG_PRIMARY_BOXED: { - Eterm hdr = *boxed_val(a); + Eterm hdr = *boxed_val_rel(a,a_base); switch (hdr & _TAG_HEADER_MASK) { case ARITYVAL_SUBTAG: { - aa = tuple_val(a); + aa = tuple_val_rel(a, a_base); if (!is_boxed(b) || *boxed_val_rel(b,b_base) != *aa) goto not_equal; bb = tuple_val_rel(b,b_base); @@ -1976,12 +1976,12 @@ tailrecur_ne: if (!is_binary_rel(b,b_base)) { goto not_equal; } - a_size = binary_size(a); + a_size = binary_size_rel(a,a_base); b_size = binary_size_rel(b,b_base); if (a_size != b_size) { goto not_equal; } - ERTS_GET_BINARY_BYTES(a, a_ptr, a_bitoffs, a_bitsize); + ERTS_GET_BINARY_BYTES_REL(a, a_ptr, a_bitoffs, a_bitsize, a_base); ERTS_GET_BINARY_BYTES_REL(b, b_ptr, b_bitoffs, b_bitsize, b_base); if ((a_bitsize | b_bitsize | a_bitoffs | b_bitoffs) == 0) { if (sys_memcmp(a_ptr, b_ptr, a_size) == 0) goto pop_next; @@ -1994,7 +1994,7 @@ tailrecur_ne: case EXPORT_SUBTAG: { if (is_export_rel(b,b_base)) { - Export* a_exp = *((Export **) (export_val(a) + 1)); + Export* a_exp = *((Export **) (export_val_rel(a,a_base) + 1)); Export* b_exp = *((Export **) (export_val_rel(b,b_base) + 1)); if (a_exp == b_exp) goto pop_next; } @@ -2007,7 +2007,7 @@ tailrecur_ne: if (!is_fun_rel(b,b_base)) goto not_equal; - f1 = (ErlFunThing *) fun_val(a); + f1 = (ErlFunThing *) fun_val_rel(a,a_base); f2 = (ErlFunThing *) fun_val_rel(b,b_base); if (f1->fe->module != f2->fe->module || f1->fe->old_index != f2->fe->old_index || @@ -2029,11 +2029,11 @@ tailrecur_ne: if(!is_external_rel(b,b_base)) goto not_equal; - ap = external_thing_ptr(a); + ap = external_thing_ptr_rel(a,a_base); bp = external_thing_ptr_rel(b,b_base); if(ap->header == bp->header && ap->node == bp->node) { - ASSERT(1 == external_data_words(a)); + ASSERT(1 == external_data_words_rel(a,a_base)); ASSERT(1 == external_data_words_rel(b,b_base)); if (ap->data.ui[0] == bp->data.ui[0]) goto pop_next; @@ -2058,7 +2058,7 @@ tailrecur_ne: if(!is_external_ref_rel(b,b_base)) goto not_equal; - athing = external_thing_ptr(a); + athing = external_thing_ptr_rel(a,a_base); bthing = external_thing_ptr_rel(b,b_base); if(athing->node != bthing->node) @@ -2075,7 +2075,7 @@ tailrecur_ne: goto not_equal; { - RefThing* athing = ref_thing_ptr(a); + RefThing* athing = ref_thing_ptr_rel(a,a_base); RefThing* bthing = ref_thing_ptr_rel(b,b_base); alen = internal_thing_ref_no_of_numbers(athing); blen = internal_thing_ref_no_of_numbers(bthing); @@ -2128,7 +2128,7 @@ tailrecur_ne: if (!is_big_rel(b,b_base)) goto not_equal; - aa = big_val(a); /* get pointer to thing */ + aa = big_val_rel(a,a_base); bb = big_val_rel(b,b_base); if (*aa != *bb) goto not_equal; @@ -2145,7 +2145,7 @@ tailrecur_ne: FloatDef bf; if (is_float_rel(b,b_base)) { - GET_DOUBLE(a, af); + GET_DOUBLE_REL(a, af, a_base); GET_DOUBLE_REL(b, bf, b_base); if (af.fd == bf.fd) goto pop_next; } @@ -2165,7 +2165,7 @@ term_array: /* arrays in 'aa' and 'bb', length in 'sz' */ Eterm* bp = bb; Sint i = sz; for (;;) { - if (!is_same(*ap,NULL,*bp,b_base)) break; + if (!is_same(*ap,a_base,*bp,b_base)) break; if (--i == 0) goto pop_next; ++ap; ++bp; -- cgit v1.2.3