diff --git a/OPTYap/tab.macros.h b/OPTYap/tab.macros.h index d0a75008f..8bfee9589 100644 --- a/OPTYap/tab.macros.h +++ b/OPTYap/tab.macros.h @@ -518,36 +518,38 @@ static inline void adjust_freeze_registers(void) { static inline void mark_as_completed(sg_fr_ptr sg_fr) { LOCK(SgFr_lock(sg_fr)); -#ifdef MODE_DIRECTED_TABLING - if (SgFr_mode_directed(sg_fr) && SgFr_invalid_chain(sg_fr)) { - ans_node_ptr current_answer, next_answer; - /* first first valid answer */ - current_answer = SgFr_first_answer(sg_fr); - while (IS_INVALID_LEAF_NODE(current_answer)) - current_answer = TrNode_child(current_answer); - SgFr_first_answer(sg_fr) = current_answer; - /* chain next valid answers */ - next_answer = TrNode_child(current_answer); - while (next_answer) { - if (! IS_INVALID_LEAF_NODE(next_answer)) { - TrNode_child(current_answer) = next_answer; - current_answer = next_answer; - } - next_answer = TrNode_child(next_answer); - } - SgFr_last_answer(sg_fr) = current_answer; - /* free invalid answer nodes */ - current_answer = SgFr_invalid_chain(sg_fr); - SgFr_invalid_chain(sg_fr) = NULL; - while (current_answer) { - next_answer = TrNode_next(current_answer); - FREE_ANSWER_TRIE_NODE(current_answer); - current_answer = next_answer; - } - } -#endif /* MODE_DIRECTED_TABLING */ SgFr_state(sg_fr) = complete; UNLOCK(SgFr_lock(sg_fr)); +#ifdef MODE_DIRECTED_TABLING + if (SgFr_invalid_chain(sg_fr)) { + ans_node_ptr current_node, next_node; + /* find first valid answer */ + current_node = SgFr_first_answer(sg_fr); + while (IS_INVALID_LEAF_NODE(current_node)) + current_node = TrNode_child(current_node); + SgFr_first_answer(sg_fr) = current_node; + /* chain next valid answers */ + next_node = TrNode_child(current_node); + while (next_node) { + if (! IS_INVALID_LEAF_NODE(next_node)) { + TrNode_child(current_node) = next_node; + current_node = next_node; + } + next_node = TrNode_child(next_node); + } + SgFr_last_answer(sg_fr) = current_node; +#ifndef YAPOR + /* free invalid answer nodes */ + current_node = SgFr_invalid_chain(sg_fr); + SgFr_invalid_chain(sg_fr) = NULL; + while (current_node) { + next_node = TrNode_next(current_node); + FREE_ANSWER_TRIE_NODE(current_node); + current_node = next_node; + } +#endif /* ! YAPOR */ + } +#endif /* MODE_DIRECTED_TABLING */ return; } @@ -753,8 +755,42 @@ static inline void abolish_incomplete_subgoals(choiceptr prune_cp) { #ifdef INCOMPLETE_TABLING SgFr_state(sg_fr) = incomplete; UNLOCK(SgFr_lock(sg_fr)); +#ifdef MODE_DIRECTED_TABLING + if (SgFr_invalid_chain(sg_fr)) { + ans_node_ptr current_node, next_node; + /* find first valid answer */ + current_node = SgFr_first_answer(sg_fr); + while (IS_INVALID_LEAF_NODE(current_node)) + current_node = TrNode_child(current_node); + SgFr_first_answer(sg_fr) = current_node; + /* chain next valid answers */ + next_node = TrNode_child(current_node); + while (next_node) { + if (! IS_INVALID_LEAF_NODE(next_node)) { + TrNode_child(current_node) = next_node; + current_node = next_node; + } + next_node = TrNode_child(next_node); + } + SgFr_last_answer(sg_fr) = current_node; +#ifndef YAPOR + /* free invalid answer nodes */ + current_node = SgFr_invalid_chain(sg_fr); + SgFr_invalid_chain(sg_fr) = NULL; + while (current_node) { + next_node = TrNode_next(invalid_node); + FREE_ANSWER_TRIE_NODE(current_node); + current_node = node_node; + } +#endif /* ! YAPOR */ + } +#endif /* MODE_DIRECTED_TABLING */ #else ans_node_ptr node; +#ifdef MODE_DIRECTED_TABLING + ans_node_ptr invalid_node = SgFr_invalid_chain(sg_fr); + SgFr_invalid_chain(sg_fr) = NULL; +#endif /* MODE_DIRECTED_TABLING */ SgFr_state(sg_fr) = ready; free_answer_hash_chain(SgFr_hash_chain(sg_fr)); SgFr_hash_chain(sg_fr) = NULL; @@ -764,6 +800,14 @@ static inline void abolish_incomplete_subgoals(choiceptr prune_cp) { TrNode_child(SgFr_answer_trie(sg_fr)) = NULL; UNLOCK(SgFr_lock(sg_fr)); free_answer_trie(node, TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST); +#if defined(MODE_DIRECTED_TABLING) && ! defined(YAPOR) + /* free invalid answer nodes */ + while (invalid_node) { + node = TrNode_next(invalid_node); + FREE_ANSWER_TRIE_NODE(invalid_node); + invalid_node = node; + } +#endif /* MODE_DIRECTED_TABLING && ! YAPOR */ #endif /* INCOMPLETE_TABLING */ } #ifdef LIMIT_TABLING diff --git a/OPTYap/tab.tries.c b/OPTYap/tab.tries.c index 353cf47c1..5ae9f2938 100644 --- a/OPTYap/tab.tries.c +++ b/OPTYap/tab.tries.c @@ -1004,8 +1004,10 @@ sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) { current_sg_node = subgoal_search_loop(tab_ent, current_sg_node, Deref(XREGS[j]), &subs_arity, &stack_vars); if (subs_arity != old_subs_arity) { if (subs_pos && MODE_DIRECTED_GET_MODE(aux_mode_directed[subs_pos-1]) == MODE_DIRECTED_GET_MODE(mode_directed[i-1])) { + /* same mode as before -> use the current entry in the aux_mode_directed[] array */ aux_mode_directed[subs_pos-1] += MODE_DIRECTED_SET(subs_arity - old_subs_arity, 0); } else { + /* new mode -> init a new entry in the aux_mode_directed[] array */ aux_mode_directed[subs_pos] = MODE_DIRECTED_SET(subs_arity - old_subs_arity, MODE_DIRECTED_GET_MODE(mode_directed[i-1])); subs_pos++; } @@ -1081,23 +1083,62 @@ ans_node_ptr answer_search(sg_fr_ptr sg_fr, CELL *subs_ptr) { #ifdef MODE_DIRECTED_TABLING mode_directed = SgFr_mode_directed(sg_fr); if (mode_directed) { + ans_node_ptr invalid_ans_node = NULL; int i = subs_arity, j = 0; while (i) { int mode = MODE_DIRECTED_GET_MODE(mode_directed[j]); int n_subs = MODE_DIRECTED_GET_ARG(mode_directed[j]); do { - TABLING_ERROR_CHECKING(answer search, IsNonVarTerm(subs_ptr[i])); - if (TrNode_child(current_ans_node) == NULL || mode == MODE_DIRECTED_INDEX || mode == MODE_DIRECTED_ALL) + TABLING_ERROR_CHECKING(answer_search, IsNonVarTerm(subs_ptr[i])); + if (mode == MODE_DIRECTED_INDEX || mode == MODE_DIRECTED_ALL) current_ans_node = answer_search_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity); - else { /* TrNode_child(current_node) != NULL && mode != MODE_DIRECTED_INDEX && mode != MODE_DIRECTED_ALL */ - if (mode == MODE_DIRECTED_FIRST) + else { +#if defined(TABLE_LOCK_AT_NODE_LEVEL) + LOCK(TrNode_lock(current_ans_node)); +#elif defined(TABLE_LOCK_AT_WRITE_LEVEL) + LOCK_TABLE(current_ans_node); +#endif /* TABLE_LOCK_LEVEL */ + if (TrNode_child(current_ans_node) == NULL) { +#ifdef YAPOR + struct answer_trie_node virtual_ans_node; + ans_node_ptr parent_ans_node = current_ans_node; + TrNode_init_lock_field(&virtual_ans_node); + TrNode_parent(&virtual_ans_node) = NULL; + TrNode_child(&virtual_ans_node) = NULL; + current_ans_node = answer_search_loop(sg_fr, &virtual_ans_node, Deref(subs_ptr[i]), &vars_arity); + TrNode_child(parent_ans_node) = TrNode_child(&virtual_ans_node); +#else + current_ans_node = answer_search_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity); +#endif /* YAPOR */ + } else if (mode == MODE_DIRECTED_MIN || mode == MODE_DIRECTED_MAX) { + ans_node_ptr parent_ans_node = current_ans_node; + invalid_ans_node = TrNode_child(parent_ans_node); /* by default, assume a better answer */ + current_ans_node = answer_search_mode_directed_min_max(sg_fr, current_ans_node, Deref(subs_ptr[i]), mode); + if (invalid_ans_node == TrNode_child(parent_ans_node)) /* worse or equal answer */ + invalid_ans_node = NULL; + } else if (mode == MODE_DIRECTED_FIRST) current_ans_node = NULL; - else if (mode == MODE_DIRECTED_LAST) { - invalidate_answer_trie(TrNode_child(current_ans_node), sg_fr, TRAVERSE_POSITION_FIRST); + else { /* mode == MODE_DIRECTED_LAST */ +#ifdef YAPOR + struct answer_trie_node virtual_ans_node; + ans_node_ptr parent_ans_node = current_ans_node; + invalid_ans_node = TrNode_child(parent_ans_node); + TrNode_init_lock_field(&virtual_ans_node); + TrNode_parent(&virtual_ans_node) = NULL; + TrNode_child(&virtual_ans_node) = NULL; + current_ans_node = answer_search_loop(sg_fr, &virtual_ans_node, Deref(subs_ptr[i]), &vars_arity); + TrNode_child(parent_ans_node) = TrNode_child(&virtual_ans_node); +#else + invalid_ans_node = TrNode_child(current_ans_node); TrNode_child(current_ans_node) = NULL; current_ans_node = answer_search_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity); - } else /* mode == MODE_DIRECTED_MIN || mode == MODE_DIRECTED_MAX */ - current_ans_node = answer_search_mode_directed_min_max(sg_fr, current_ans_node, Deref(subs_ptr[i]), mode); +#endif /* YAPOR */ + } +#if defined(TABLE_LOCK_AT_NODE_LEVEL) + UNLOCK(TrNode_lock(current_ans_node)); +#elif defined(TABLE_LOCK_AT_WRITE_LEVEL) + UNLOCK_TABLE(current_ans_node); +#endif /* TABLE_LOCK_LEVEL */ } n_subs--; i--; @@ -1106,16 +1147,18 @@ ans_node_ptr answer_search(sg_fr_ptr sg_fr, CELL *subs_ptr) { break; j++; } + if (invalid_ans_node) + invalidate_answer_trie(invalid_ans_node, sg_fr, TRAVERSE_POSITION_FIRST); } else #endif /* MODE_DIRECTED_TABLING */ if (IsMode_GlobalTrie(TabEnt_mode(SgFr_tab_ent(sg_fr)))) { for (i = subs_arity; i >= 1; i--) { - TABLING_ERROR_CHECKING(answer search, IsNonVarTerm(subs_ptr[i])); + TABLING_ERROR_CHECKING(answer_search, IsNonVarTerm(subs_ptr[i])); current_ans_node = answer_search_terms_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity); } } else { for (i = subs_arity; i >= 1; i--) { - TABLING_ERROR_CHECKING(answer search, IsNonVarTerm(subs_ptr[i])); + TABLING_ERROR_CHECKING(answer_search, IsNonVarTerm(subs_ptr[i])); current_ans_node = answer_search_loop(sg_fr, current_ans_node, Deref(subs_ptr[i]), &vars_arity); } } @@ -1234,6 +1277,18 @@ void free_subgoal_trie(sg_node_ptr current_node, int mode, int position) { if (TrNode_child(ans_node)) free_answer_trie(TrNode_child(ans_node), TRAVERSE_MODE_NORMAL, TRAVERSE_POSITION_FIRST); FREE_ANSWER_TRIE_NODE(ans_node); +#if defined(MODE_DIRECTED_TABLING) && defined(YAPOR) + if (SgFr_invalid_chain(sg_fr)) { + ans_node_ptr next_node, invalid_node = SgFr_invalid_chain(sg_fr); + SgFr_invalid_chain(sg_fr) = NULL; + /* free invalid answer nodes */ + while (invalid_node) { + next_node = TrNode_next(invalid_node); + FREE_ANSWER_TRIE_NODE(invalid_node); + invalid_node = next_node; + } + } +#endif /* MODE_DIRECTED_TABLING && YAPOR */ #ifdef LIMIT_TABLING remove_from_global_sg_fr_list(sg_fr); #endif /* LIMIT_TABLING */ diff --git a/OPTYap/tab.tries.i b/OPTYap/tab.tries.i index 0312bfbd2..4278bfe53 100644 --- a/OPTYap/tab.tries.i +++ b/OPTYap/tab.tries.i @@ -1203,8 +1203,14 @@ static inline ans_node_ptr answer_search_loop(sg_fr_ptr sg_fr, ans_node_ptr curr ****************************************************************************/ #if defined(MODE_DIRECTED_TABLING) && ! defined(MODE_TERMS_LOOP) && ! defined(MODE_GLOBAL_TRIE_LOOP) +#define ANSWER_SAFE_INSERT_ENTRY(NODE, ENTRY, INSTR) \ + { ans_node_ptr new_node; \ + NEW_ANSWER_TRIE_NODE(new_node, INSTR, ENTRY, NULL, NODE, NULL); \ + TrNode_child(NODE) = new_node; \ + NODE = new_node; \ + } + static inline ans_node_ptr answer_search_mode_directed_min_max(sg_fr_ptr sg_fr, ans_node_ptr current_node, Term t, int mode) { -#define in_pair 0 ans_node_ptr child_node; Term child_term; Float trie_value, term_value; @@ -1255,10 +1261,8 @@ static inline ans_node_ptr answer_search_mode_directed_min_max(sg_fr_ptr sg_fr, if (term_value == trie_value) return child_node; /* better answer */ - invalidate_answer_trie(TrNode_child(current_node), sg_fr, TRAVERSE_POSITION_FIRST); - TrNode_child(current_node) = NULL; if (IsAtomOrIntTerm(t)) { - ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, t, _trie_retry_atom + in_pair); + ANSWER_SAFE_INSERT_ENTRY(current_node, t, _trie_retry_atom); } else if (IsApplTerm(t)) { Functor f = FunctorOfTerm(t); if (f == FunctorDouble) { @@ -1267,21 +1271,20 @@ static inline ans_node_ptr answer_search_mode_directed_min_max(sg_fr_ptr sg_fr, Float dbl; } u; u.dbl = FloatOfTerm(t); - ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_null + in_pair); + ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null); #if SIZEOF_DOUBLE == 2 * SIZEOF_INT_P - ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, u.t_dbl[1], _trie_retry_extension); + ANSWER_SAFE_INSERT_ENTRY(current_node, u.t_dbl[1], _trie_retry_extension); #endif /* SIZEOF_DOUBLE x SIZEOF_INT_P */ - ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, u.t_dbl[0], _trie_retry_extension); - ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_double); + ANSWER_SAFE_INSERT_ENTRY(current_node, u.t_dbl[0], _trie_retry_extension); + ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_double); } else if (f == FunctorLongInt) { Int li = LongIntOfTerm(t); - ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_null + in_pair); - ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, li, _trie_retry_extension); - ANSWER_CHECK_INSERT_ENTRY(sg_fr, current_node, AbsAppl((Term *)f), _trie_retry_longint); + ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_null); + ANSWER_SAFE_INSERT_ENTRY(current_node, li, _trie_retry_extension); + ANSWER_SAFE_INSERT_ENTRY(current_node, AbsAppl((Term *)f), _trie_retry_longint); } } return current_node; -#undef in_pair }