aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2010-12-15 17:20:46 +0100
committerSverker Eriksson <[email protected]>2011-02-03 17:33:43 +0100
commit651c99b7aac8ac7ca7f84efa0d3bd3b541d6f3a4 (patch)
tree29e555424f947f7a29fa615dd89de5c9017b6d5b
parent561f6fd2bc8367acd1bceea291303adb18ad0b93 (diff)
downloadotp-651c99b7aac8ac7ca7f84efa0d3bd3b541d6f3a4.tar.gz
otp-651c99b7aac8ac7ca7f84efa0d3bd3b541d6f3a4.tar.bz2
otp-651c99b7aac8ac7ca7f84efa0d3bd3b541d6f3a4.zip
HALFWORD ETS Real matching on relative terms
-rw-r--r--erts/emulator/beam/erl_db.c2
-rw-r--r--erts/emulator/beam/erl_db_hash.c2
-rw-r--r--erts/emulator/beam/erl_db_util.c81
-rw-r--r--erts/emulator/beam/erl_db_util.h7
-rw-r--r--erts/emulator/beam/global.h8
-rw-r--r--erts/emulator/beam/sys.h2
-rw-r--r--erts/emulator/beam/utils.c40
7 files changed, 78 insertions, 64 deletions
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;