From b36b836820b3df994ac535d9afa9401e91312f72 Mon Sep 17 00:00:00 2001 From: ricroc Date: Mon, 1 Aug 2005 15:40:39 +0000 Subject: [PATCH] TABLING NEW: better support for incomplete tabling git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1351 b08c6af1-5177-4d33-ba66-4b1c6b8b522a --- C/absmi.c | 18 +++-- C/cdmgr.c | 16 ++-- C/heapgc.c | 62 +++++++-------- C/index.c | 11 ++- C/init.c | 6 +- H/Heap.h | 8 +- H/YapOpcodes.h | 8 +- H/rclause.h | 8 +- H/rheap.h | 11 ++- OPTYap/opt.config.h | 10 ++- OPTYap/opt.macros.h | 36 ++++----- OPTYap/opt.preds.c | 9 ++- OPTYap/opt.proto.h | 7 +- OPTYap/tab.insts.i | 177 ++++++++++++++++++++++++++++++++++--------- OPTYap/tab.macros.h | 23 +++--- OPTYap/tab.structs.h | 44 ++++++----- OPTYap/tab.tries.c | 164 ++++++++++++++++++++------------------- 17 files changed, 394 insertions(+), 224 deletions(-) diff --git a/C/absmi.c b/C/absmi.c index 15967b113..751ac6913 100644 --- a/C/absmi.c +++ b/C/absmi.c @@ -10,8 +10,11 @@ * * * File: absmi.c * * comments: Portable abstract machine interpreter * -* Last rev: $Date: 2005-07-06 19:33:51 $,$Author: ricroc $ * +* Last rev: $Date: 2005-08-01 15:40:36 $,$Author: ricroc $ * * $Log: not supported by cvs2svn $ +* Revision 1.170 2005/07/06 19:33:51 ricroc +* TABLING: answers for completed calls can now be obtained by loading (new option) or executing (default) them from the trie data structure. +* * Revision 1.169 2005/07/06 15:10:01 vsc * improvements to compiler: merged instructions and fixes for -> * @@ -1408,20 +1411,19 @@ Yap_absmi(int inp) go_on = FALSE; switch (opnum) { #ifdef TABLING + case _table_load_answer: + low_level_trace(retry_table_loader, LOAD_CP(B)->cp_pred_entry, NULL); + break; + case _table_try_answer: case _table_retry_me: case _table_trust_me: case _table_retry: case _table_trust: - low_level_trace(retry_table_generator, TabEnt_pe(GEN_CP(B)->cp_tab_ent), (CELL *)(GEN_CP(B)+ 1)); - break; case _table_completion: - low_level_trace(retry_table_generator, TabEnt_pe(GEN_CP(B)->cp_tab_ent), (CELL *)(GEN_CP(B)+1)); + low_level_trace(retry_table_generator, GEN_CP(B)->cp_pred_entry, (CELL *)(GEN_CP(B) + 1)); break; case _table_answer_resolution: - low_level_trace(retry_table_consumer, TabEnt_pe(CONS_CP(B)->cp_tab_ent), NULL); - break; - case _table_load_answer: - low_level_trace(retry_table_loader, TabEnt_pe(LOAD_CP(B)->cp_tab_ent), NULL); + low_level_trace(retry_table_consumer, CONS_CP(B)->cp_pred_entry, NULL); break; case _trie_retry_null: case _trie_trust_null: diff --git a/C/cdmgr.c b/C/cdmgr.c index 210f55f58..9be4d9306 100644 --- a/C/cdmgr.c +++ b/C/cdmgr.c @@ -11,8 +11,11 @@ * File: cdmgr.c * * comments: Code manager * * * -* Last rev: $Date: 2005-07-06 19:33:52 $,$Author: ricroc $ * +* Last rev: $Date: 2005-08-01 15:40:37 $,$Author: ricroc $ * * $Log: not supported by cvs2svn $ +* Revision 1.165 2005/07/06 19:33:52 ricroc +* TABLING: answers for completed calls can now be obtained by loading (new option) or executing (default) them from the trie data structure. +* * Revision 1.164 2005/07/06 15:10:03 vsc * improvements to compiler: merged instructions and fixes for -> * @@ -311,12 +314,13 @@ PredForChoicePt(yamop *p_code) { case _trie_retry_long: case _trie_trust_long: return NULL; + case _table_load_answer: + case _table_try_answer: case _table_answer_resolution: case _table_completion: - case _table_load_answer: return NULL; /* ricroc: is this OK? */ /* compile error --> return ENV_ToP(gc_B->cp_cp); */ -#endif +#endif /* TABLING */ case _or_else: if (p_code == p_code->u.sla.sla_u.l) { /* repeat */ @@ -331,7 +335,7 @@ PredForChoicePt(yamop *p_code) { return p_code->u.sla.p0; #else return p_code->u.p.p; -#endif +#endif /* YAPOR */ break; case _trust_logical_pred: case _count_retry_me: @@ -444,7 +448,7 @@ Yap_BuildMegaClause(PredEntry *ap) if (ap->PredFlags & (DynamicPredFlag|LogUpdatePredFlag|MegaClausePredFlag #ifdef TABLING |TabledPredFlag -#endif +#endif /* TABLING */ ) || ap->cs.p_code.FirstClause == NULL || ap->cs.p_code.NOfClauses < 16) { @@ -663,7 +667,7 @@ RemoveMainIndex(PredEntry *ap) } else if (ap->cs.p_code.NOfClauses > 1 #ifdef TABLING ||ap->PredFlags & TabledPredFlag -#endif +#endif /* TABLING */ ) { ap->OpcodeOfPred = INDEX_OPCODE; ap->CodeOfPred = ap->cs.p_code.TrueCodeOfPred = (yamop *)(&(ap->OpcodeOfPred)); diff --git a/C/heapgc.c b/C/heapgc.c index bc01a8ef9..c503980ce 100644 --- a/C/heapgc.c +++ b/C/heapgc.c @@ -1828,6 +1828,19 @@ mark_choicepoints(register choiceptr gc_B, tr_fr_ptr saved_TR, int very_verbose) nargs = 0; break; #ifdef TABLING + case _table_load_answer: + { + CELL *vars_ptr, vars; + vars_ptr = (CELL *) (LOAD_CP(gc_B) + 1); + vars = *vars_ptr++; + while (vars--) { + mark_external_reference(vars_ptr); + vars_ptr++; + } + } + nargs = 0; + break; + case _table_try_answer: case _table_retry_me: case _table_trust_me: case _table_retry: @@ -1877,18 +1890,6 @@ mark_choicepoints(register choiceptr gc_B, tr_fr_ptr saved_TR, int very_verbose) } nargs = 0; break; - case _table_load_answer: - { - CELL *vars_ptr, vars; - vars_ptr = (CELL *) (LOAD_CP(gc_B) + 1); - vars = *vars_ptr++; - while (vars--) { - mark_external_reference(vars_ptr); - vars_ptr++; - } - } - nargs = 0; - break; case _trie_retry_null: case _trie_trust_null: case _trie_retry_var: @@ -2548,6 +2549,25 @@ sweep_choicepoints(choiceptr gc_B) opnum = Yap_op_from_opcode(op); goto restart_cp; #ifdef TABLING + case _table_load_answer: + { + CELL *vars_ptr, vars; + sweep_environments(gc_B->cp_env, EnvSize((CELL_PTR) (gc_B->cp_cp)), EnvBMap((CELL_PTR) (gc_B->cp_cp))); + vars_ptr = (CELL *) (LOAD_CP(gc_B) + 1); + vars = *vars_ptr++; + while (vars--) { + CELL cp_cell = *vars_ptr; + if (MARKED_PTR(vars_ptr)) { + UNMARK(vars_ptr); + if (HEAP_PTR(cp_cell)) { + into_relocation_chain(vars_ptr, GET_NEXT(cp_cell)); + } + } + vars_ptr++; + } + } + break; + case _table_try_answer: case _table_retry_me: case _table_trust_me: case _table_retry: @@ -2629,24 +2649,6 @@ sweep_choicepoints(choiceptr gc_B) } } break; - case _table_load_answer: - { - CELL *vars_ptr, vars; - sweep_environments(gc_B->cp_env, EnvSize((CELL_PTR) (gc_B->cp_cp)), EnvBMap((CELL_PTR) (gc_B->cp_cp))); - vars_ptr = (CELL *) (LOAD_CP(gc_B) + 1); - vars = *vars_ptr++; - while (vars--) { - CELL cp_cell = *vars_ptr; - if (MARKED_PTR(vars_ptr)) { - UNMARK(vars_ptr); - if (HEAP_PTR(cp_cell)) { - into_relocation_chain(vars_ptr, GET_NEXT(cp_cell)); - } - } - vars_ptr++; - } - } - break; case _trie_retry_null: case _trie_trust_null: case _trie_retry_var: diff --git a/C/index.c b/C/index.c index 99096609f..2a99bac30 100644 --- a/C/index.c +++ b/C/index.c @@ -11,8 +11,11 @@ * File: index.c * * comments: Indexing a Prolog predicate * * * -* Last rev: $Date: 2005-07-19 16:54:20 $,$Author: rslopes $ * +* Last rev: $Date: 2005-08-01 15:40:37 $,$Author: ricroc $ * * $Log: not supported by cvs2svn $ +* Revision 1.141 2005/07/19 16:54:20 rslopes +* fix for older compilers... +* * Revision 1.140 2005/07/18 17:41:16 vsc * Yap should respect single argument indexing. * @@ -709,13 +712,14 @@ has_cut(yamop *pc) case _sync: #endif /* YAPOR */ #ifdef TABLING + case _table_load_answer: + case _table_try_answer: case _table_try_me_single: case _table_try_me: case _table_retry_me: case _table_trust_me: case _table_answer_resolution: case _table_completion: - case _table_load_answer: #endif /* TABLING */ pc = NEXTOP(pc,ld); break; @@ -2129,6 +2133,8 @@ add_info(ClauseDef *clause, UInt regno) case _table_try_single: cl = NEXTOP(cl,ld); break; + case _table_load_answer: + case _table_try_answer: case _table_try_me: case _table_retry_me: case _table_trust_me: @@ -2137,7 +2143,6 @@ add_info(ClauseDef *clause, UInt regno) case _table_trust: case _table_answer_resolution: case _table_completion: - case _table_load_answer: #endif /* TABLING */ case _enter_profiling: case _count_call: diff --git a/C/init.c b/C/init.c index c07730f50..e10d01d1d 100644 --- a/C/init.c +++ b/C/init.c @@ -783,13 +783,15 @@ InitCodes(void) Yap_heap_regs->getwork_first_time_code.opc = Yap_opcode(_getwork_first_time); #endif /* YAPOR */ #ifdef TABLING + Yap_heap_regs->table_load_answer_code.opc = Yap_opcode(_table_load_answer); + Yap_heap_regs->table_try_answer_code.opc = Yap_opcode(_table_try_answer); Yap_heap_regs->table_completion_code.opc = Yap_opcode(_table_completion); Yap_heap_regs->table_answer_resolution_code.opc = Yap_opcode(_table_answer_resolution); - Yap_heap_regs->table_load_answer_code.opc = Yap_opcode(_table_load_answer); #ifdef YAPOR + INIT_YAMOP_LTT(&(Yap_heap_regs->table_load_answer_code), 0); + INIT_YAMOP_LTT(&(Yap_heap_regs->table_try_answer_code), 0); INIT_YAMOP_LTT(&(Yap_heap_regs->table_completion_code), 0); INIT_YAMOP_LTT(&(Yap_heap_regs->table_answer_resolution_code), 0); - INIT_YAMOP_LTT(&(Yap_heap_regs->table_load_answer_code), 0); #endif /* YAPOR */ #endif /* TABLING */ Yap_heap_regs->expand_op_code = Yap_opcode(_expand_index); diff --git a/H/Heap.h b/H/Heap.h index 071d74309..1e041c75b 100644 --- a/H/Heap.h +++ b/H/Heap.h @@ -10,7 +10,7 @@ * File: Heap.h * * mods: * * comments: Heap Init Structure * -* version: $Id: Heap.h,v 1.81 2005-07-06 19:34:11 ricroc Exp $ * +* version: $Id: Heap.h,v 1.82 2005-08-01 15:40:38 ricroc Exp $ * *************************************************************************/ /* information that can be stored in Code Space */ @@ -141,9 +141,10 @@ typedef struct various_codes { yamop getwork_first_time_code; #endif /* YAPOR */ #ifdef TABLING + yamop table_load_answer_code; + yamop table_try_answer_code; yamop table_answer_resolution_code; yamop table_completion_code; - yamop table_load_answer_code; #endif /* TABLING */ OPCODE expand_op_code; yamop *expand_clauses_first, *expand_clauses_last; @@ -469,9 +470,10 @@ struct various_codes *Yap_heap_regs; #define GETWORK_FIRST_TIME (&(Yap_heap_regs->getwork_first_time_code)) #endif /* YAPOR */ #ifdef TABLING +#define LOAD_ANSWER ((yamop *)&(Yap_heap_regs->table_load_answer_code)) +#define TRY_ANSWER ((yamop *)&(Yap_heap_regs->table_try_answer_code)) #define ANSWER_RESOLUTION ((yamop *)&(Yap_heap_regs->table_answer_resolution_code)) #define COMPLETION ((yamop *)&(Yap_heap_regs->table_completion_code)) -#define LOAD_ANSWER ((yamop *)&(Yap_heap_regs->table_load_answer_code)) #endif /* TABLING */ #define EXPAND_OP_CODE Yap_heap_regs->expand_op_code #define ExpandClausesFirst Yap_heap_regs->expand_clauses_first diff --git a/H/YapOpcodes.h b/H/YapOpcodes.h index 53561199d..7411c8e75 100644 --- a/H/YapOpcodes.h +++ b/H/YapOpcodes.h @@ -11,8 +11,11 @@ * File: YapOpcodes.h * * comments: Central Table with all YAP opcodes * * * -* Last rev: $Date: 2005-07-06 19:34:11 $ * +* Last rev: $Date: 2005-08-01 15:40:38 $ * * $Log: not supported by cvs2svn $ +* Revision 1.32 2005/07/06 19:34:11 ricroc +* TABLING: answers for completed calls can now be obtained by loading (new option) or executing (default) them from the trie data structure. +* * Revision 1.31 2005/07/06 15:10:15 vsc * improvements to compiler: merged instructions and fixes for -> * @@ -76,6 +79,8 @@ OPCODE(clause_with_cut ,e), #endif /* TABLING_INNER_CUTS */ #ifdef TABLING + OPCODE(table_load_answer ,ld), + OPCODE(table_try_answer ,ld), OPCODE(table_try_single ,ld), OPCODE(table_try_me ,ld), OPCODE(table_try ,ld), @@ -86,7 +91,6 @@ OPCODE(table_new_answer ,s), OPCODE(table_answer_resolution ,ld), OPCODE(table_completion ,ld), - OPCODE(table_load_answer ,ld), OPCODE(trie_do_null ,e), OPCODE(trie_trust_null ,e), diff --git a/H/rclause.h b/H/rclause.h index 0e5343879..67a510809 100644 --- a/H/rclause.h +++ b/H/rclause.h @@ -12,8 +12,11 @@ * File: rclause.h * * comments: walk through a clause * * * -* Last rev: $Date: 2005-07-06 19:34:11 $,$Author: ricroc $ * +* Last rev: $Date: 2005-08-01 15:40:38 $,$Author: ricroc $ * * $Log: not supported by cvs2svn $ +* Revision 1.9 2005/07/06 19:34:11 ricroc +* TABLING: answers for completed calls can now be obtained by loading (new option) or executing (default) them from the trie data structure. +* * Revision 1.8 2005/07/06 15:10:15 vsc * improvements to compiler: merged instructions and fixes for -> * @@ -124,6 +127,8 @@ restore_opcodes(yamop *pc) case _sync: #endif #ifdef TABLING + case _table_load_answer: + case _table_try_answer: case _table_try_single: case _table_try_me: case _table_retry_me: @@ -133,7 +138,6 @@ restore_opcodes(yamop *pc) case _table_trust: case _table_answer_resolution: case _table_completion: - case _table_load_answer: #endif /* TABLING */ pc->u.ld.p = PtoPredAdjust(pc->u.ld.p); pc->u.ld.d = PtoOpAdjust(pc->u.ld.d); diff --git a/H/rheap.h b/H/rheap.h index 7c73635a8..d777bc503 100644 --- a/H/rheap.h +++ b/H/rheap.h @@ -11,8 +11,11 @@ * File: rheap.h * * comments: walk through heap code * * * -* Last rev: $Date: 2005-07-06 19:34:11 $,$Author: ricroc $ * +* Last rev: $Date: 2005-08-01 15:40:38 $,$Author: ricroc $ * * $Log: not supported by cvs2svn $ +* Revision 1.52 2005/07/06 19:34:11 ricroc +* TABLING: answers for completed calls can now be obtained by loading (new option) or executing (default) them from the trie data structure. +* * Revision 1.51 2005/07/06 15:10:15 vsc * improvements to compiler: merged instructions and fixes for -> * @@ -114,13 +117,15 @@ restore_codes(void) Yap_heap_regs->getwork_first_time_code.opc = Yap_opcode(_getwork_first_time); #endif /* YAPOR */ #ifdef TABLING + Yap_heap_regs->table_load_answer_code.opc = Yap_opcode(_table_load_answer); + Yap_heap_regs->table_try_answer_code.opc = Yap_opcode(_table_try_answer); Yap_heap_regs->table_answer_resolution_code.opc = Yap_opcode(_table_answer_resolution); Yap_heap_regs->table_completion_code.opc = Yap_opcode(_table_completion); - Yap_heap_regs->table_load_answer_code.opc = Yap_opcode(_table_load_answer); #ifdef YAPOR + INIT_YAMOP_LTT(&(Yap_heap_regs->table_load_answer_code), 0); + INIT_YAMOP_LTT(&(Yap_heap_regs->table_try_answer_code), 0); INIT_YAMOP_LTT(&(Yap_heap_regs->table_completion_code), 0); INIT_YAMOP_LTT(&(Yap_heap_regs->table_answer_resolution_code), 0); - INIT_YAMOP_LTT(&(Yap_heap_regs->table_load_answer_code), 0); #endif /* YAPOR */ #endif /* TABLING */ Yap_heap_regs->expand_op_code = Yap_opcode(_expand_index); diff --git a/OPTYap/opt.config.h b/OPTYap/opt.config.h index d7e92f41f..74f4eb33d 100644 --- a/OPTYap/opt.config.h +++ b/OPTYap/opt.config.h @@ -5,7 +5,7 @@ Copyright: R. Rocha and NCC - University of Porto, Portugal File: opt.config.h - version: $Id: opt.config.h,v 1.7 2005-07-11 19:17:24 ricroc Exp $ + version: $Id: opt.config.h,v 1.8 2005-08-01 15:40:38 ricroc Exp $ **********************************************************************/ @@ -63,6 +63,11 @@ /* #define TABLE_LOCK_AT_NODE_LEVEL 1 */ /* #define ALLOC_BEFORE_CHECK 1 */ +/* ----------------------------------------------- ** +** support incomplete tabling? (optional) ** +** ----------------------------------------------- */ +/* #define INCOMPLETE_TABLING 1 */ + /* --------------------------------------- ** ** support inner cuts? (optional) ** ** --------------------------------------- */ @@ -155,9 +160,12 @@ #ifndef YAPOR #undef YAPOR_ERRORS #endif /* !YAPOR */ + #ifndef TABLING +#undef INCOMPLETE_TABLING #undef TABLING_ERRORS #endif /* !TABLING */ + #if defined(YAPOR_ERRORS) && defined(TABLING_ERRORS) #define OPTYAP_ERRORS #endif /* YAPOR_ERRORS && TABLING_ERRORS */ diff --git a/OPTYap/opt.macros.h b/OPTYap/opt.macros.h index b4cea2b8f..d9cabe528 100644 --- a/OPTYap/opt.macros.h +++ b/OPTYap/opt.macros.h @@ -5,7 +5,7 @@ Copyright: R. Rocha and NCC - University of Porto, Portugal File: opt.macros.h - version: $Id: opt.macros.h,v 1.7 2005-07-11 19:17:27 ricroc Exp $ + version: $Id: opt.macros.h,v 1.8 2005-08-01 15:40:38 ricroc Exp $ **********************************************************************/ @@ -51,11 +51,6 @@ extern int Yap_page_size; #define UPDATE_STATS(STAT, VALUE) STAT += VALUE #ifdef MALLOC_MEMORY_ALLOC_SCHEME /* --------------------------------------------- */ -#define ALLOC_BLOCK(BLOCK, SIZE) \ - if ((BLOCK = malloc(SIZE)) == NULL) \ - Yap_Error(FATAL_ERROR, TermNil, "malloc error (ALLOC_BLOCK)") -#define FREE_BLOCK(BLOCK) \ - free(BLOCK) #define ALLOC_STRUCT(STR, STR_PAGES, STR_TYPE) \ UPDATE_STATS(Pg_str_in_use(STR_PAGES), 1); \ if ((STR = (STR_TYPE *)malloc(sizeof(STR_TYPE))) == NULL) \ @@ -66,11 +61,6 @@ extern int Yap_page_size; UPDATE_STATS(Pg_str_in_use(STR_PAGES), -1); \ free(STR) #elif YAP_MEMORY_ALLOC_SCHEME /* ----------------------------------------------- */ -#define ALLOC_BLOCK(BLOCK, SIZE) \ - if ((BLOCK = (void *) Yap_AllocCodeSpace(SIZE)) == NULL) \ - Yap_Error(FATAL_ERROR, TermNil, "Yap_AllocCodeSpace error (ALLOC_BLOCK)") -#define FREE_BLOCK(BLOCK) \ - Yap_FreeCodeSpace((char *) (BLOCK)) #define ALLOC_STRUCT(STR, STR_PAGES, STR_TYPE) \ UPDATE_STATS(Pg_str_in_use(STR_PAGES), 1); \ if ((STR = (STR_TYPE *) Yap_AllocCodeSpace(sizeof(STR_TYPE))) == NULL) \ @@ -81,12 +71,6 @@ extern int Yap_page_size; UPDATE_STATS(Pg_str_in_use(STR_PAGES), -1); \ Yap_FreeCodeSpace((char *) (STR)) #elif SHM_MEMORY_ALLOC_SCHEME /* ------------------------------------------------ */ -#define ALLOC_BLOCK(BLOCK, SIZE) \ - if ((BLOCK = (void *) Yap_AllocCodeSpace(SIZE)) == NULL) \ - Yap_Error(FATAL_ERROR, TermNil, "Yap_AllocCodeSpace error (ALLOC_BLOCK)") -#define FREE_BLOCK(BLOCK) \ - Yap_FreeCodeSpace((char *) (BLOCK)) - #define ALLOC_PAGE(PG_HD) \ LOCK(Pg_lock(GLOBAL_PAGES_void)); \ UPDATE_STATS(Pg_str_in_use(GLOBAL_PAGES_void), 1); \ @@ -216,6 +200,22 @@ extern int Yap_page_size; } #endif /* ------------------------- MEMORY_ALLOC_SCHEME -------------------------- */ + + +#ifdef YAPOR +#define ALLOC_BLOCK(BLOCK, SIZE) \ + if ((BLOCK = (void *) Yap_AllocCodeSpace(SIZE)) == NULL) \ + Yap_Error(FATAL_ERROR, TermNil, "Yap_AllocCodeSpace error (ALLOC_BLOCK)") +#define FREE_BLOCK(BLOCK) \ + Yap_FreeCodeSpace((char *) (BLOCK)) +#else /* TABLING */ +#define ALLOC_BLOCK(BLOCK, SIZE) \ + if ((BLOCK = malloc(SIZE)) == NULL) \ + Yap_Error(FATAL_ERROR, TermNil, "malloc error (ALLOC_BLOCK)") +#define FREE_BLOCK(BLOCK) \ + free(BLOCK) +#endif /* YAPOR - TABLING */ + #define ALLOC_HASH_BUCKETS(BUCKET_PTR, NUM_BUCKETS) \ { int i; void **ptr; \ ALLOC_BLOCK(ptr, NUM_BUCKETS * sizeof(void *)); \ @@ -225,6 +225,8 @@ extern int Yap_page_size; } #define FREE_HASH_BUCKETS(BUCKET_PTR) FREE_BLOCK(BUCKET_PTR) + + #define ALLOC_OR_FRAME(STR) ALLOC_STRUCT(STR, GLOBAL_PAGES_or_fr, struct or_frame) #define FREE_OR_FRAME(STR) FREE_STRUCT(STR, GLOBAL_PAGES_or_fr, struct or_frame) diff --git a/OPTYap/opt.preds.c b/OPTYap/opt.preds.c index 8c4e39d6c..27d7a846a 100644 --- a/OPTYap/opt.preds.c +++ b/OPTYap/opt.preds.c @@ -5,7 +5,7 @@ Copyright: R. Rocha and NCC - University of Porto, Portugal File: opt.preds.c - version: $Id: opt.preds.c,v 1.21 2005-07-28 16:29:50 ricroc Exp $ + version: $Id: opt.preds.c,v 1.22 2005-08-01 15:40:38 ricroc Exp $ **********************************************************************/ @@ -678,7 +678,8 @@ int p_show_table(void) { tab_ent = RepPredProp(PredPropByFunc(FunctorOfTerm(t), mod))->TableOfPred; } else return (FALSE); - traverse_trie(tab_ent, at, TRUE); + fprintf(Yap_stderr, "Table structure for predicate '%s/%d'\n", AtomName(at), TabEnt_arity(tab_ent)); + traverse_table(tab_ent, at, TRUE); return (TRUE); } @@ -699,7 +700,9 @@ int p_table_statistics(void) { tab_ent = RepPredProp(PredPropByFunc(FunctorOfTerm(t), mod))->TableOfPred; } else return (FALSE); - traverse_trie(tab_ent, at, FALSE); + fprintf(Yap_stderr, "Table statistics for predicate '%s/%d'", AtomName(at), TabEnt_arity(tab_ent)); + if (traverse_table(tab_ent, at, FALSE)) + table_stats(); return (TRUE); } diff --git a/OPTYap/opt.proto.h b/OPTYap/opt.proto.h index d3abc5cdf..b2ef32dff 100644 --- a/OPTYap/opt.proto.h +++ b/OPTYap/opt.proto.h @@ -5,7 +5,7 @@ Copyright: R. Rocha and NCC - University of Porto, Portugal File: opt.proto.h - version: $Id: opt.proto.h,v 1.9 2005-07-11 19:17:27 ricroc Exp $ + version: $Id: opt.proto.h,v 1.10 2005-08-01 15:40:38 ricroc Exp $ **********************************************************************/ @@ -63,14 +63,15 @@ void finish_yapor(void); ** ------------- */ #ifdef TABLING -sg_fr_ptr subgoal_search(tab_ent_ptr tab_ent, OPREG arity, CELL **Yaddr); +sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr); ans_node_ptr answer_search(sg_fr_ptr sg_fr, CELL *subs_ptr); void load_answer_trie(ans_node_ptr ans_node, CELL *subs_ptr); void private_completion(sg_fr_ptr sg_fr); void free_subgoal_trie_branch(sg_node_ptr node, int missing_nodes); void free_answer_trie_branch(ans_node_ptr node); void update_answer_trie(sg_fr_ptr sg_fr); -void traverse_trie(tab_ent_ptr tab_ent, Atom pred_atom, int show_trie); +int traverse_table(tab_ent_ptr tab_ent, Atom pred_atom, int show_table); +void table_stats(void); #endif /* TABLING */ diff --git a/OPTYap/tab.insts.i b/OPTYap/tab.insts.i index 649943ae8..2f05fec00 100644 --- a/OPTYap/tab.insts.i +++ b/OPTYap/tab.insts.i @@ -5,7 +5,7 @@ Copyright: R. Rocha and NCC - University of Porto, Portugal File: tab.insts.i - version: $Id: tab.insts.i,v 1.16 2005-07-06 19:34:10 ricroc Exp $ + version: $Id: tab.insts.i,v 1.17 2005-08-01 15:40:38 ricroc Exp $ **********************************************************************/ @@ -14,7 +14,7 @@ ** ------------------------------------------------ */ #ifdef LOW_LEVEL_TRACER -#define store_low_level_trace_info(CP, TAB_ENT) CP->cp_tab_ent = TAB_ENT +#define store_low_level_trace_info(CP, TAB_ENT) CP->cp_pred_entry = TabEnt_pe(TAB_ENT) #else #define store_low_level_trace_info(CP, TAB_ENT) #endif /* LOW_LEVEL_TRACER */ @@ -273,16 +273,115 @@ + PBOp(table_load_answer, ld) + CELL *subs_ptr; + ans_node_ptr ans_node; + +#ifdef YAPOR + if (SCH_top_shared_cp(B)) { + PROBLEM: cp_last_answer field is local to the cp! + -> we need a shared data structure to avoid redundant computations! + UNLOCK_OR_FRAME(LOCAL_top_or_fr); + } +#endif /* YAPOR */ + subs_ptr = (CELL *) (LOAD_CP(B) + 1); + ans_node = TrNode_child(LOAD_CP(B)->cp_last_answer); + if(TrNode_child(ans_node) != NULL) { + restore_loader_node(ans_node); + } else { + pop_loader_node(); + } + PREG = (yamop *) CPREG; + PREFETCH_OP(PREG); + load_answer_trie(ans_node, subs_ptr); + YENV = ENV; + GONext(); + ENDPBOp(); + + + + PBOp(table_try_answer, ld) +#ifdef INCOMPLETE_TABLING + sg_fr_ptr sg_fr; + ans_node_ptr ans_node; + + sg_fr = GEN_CP(B)->cp_sg_fr; + ans_node = TrNode_child(SgFr_try_answer(sg_fr)); + if(ans_node) { + CELL *subs_ptr = (CELL *) (GEN_CP(B) + 1) + SgFr_arity(sg_fr); + + H = HBREG = PROTECT_FROZEN_H(B); + restore_yaam_reg_cpdepth(B); + CPREG = B->cp_cp; + ENV = B->cp_env; + SgFr_try_answer(sg_fr) = ans_node; +#ifdef YAPOR + if (SCH_top_shared_cp(B)) + UNLOCK_OR_FRAME(LOCAL_top_or_fr); +#endif /* YAPOR */ + SET_BB(PROTECT_FROZEN_B(B)); + + PREG = (yamop *) CPREG; + PREFETCH_OP(PREG); + load_answer_trie(ans_node, subs_ptr); + YENV = ENV; + GONext(); + } else { + yamop *code_ap; + OPCODE code = Yap_opcode(_table_try_me); + PREG = SgFr_code(sg_fr); + if (PREG->opc > code) { + /* table_try */ + code_ap = NEXTOP(PREG,ld); + PREG = PREG->u.ld.d; + } else if (PREG->opc == code) { + /* table_try_me */ + code_ap = PREG->u.ld.d; + PREG = NEXTOP(PREG,ld); + } else { + /* table_try_single */ + code_ap = COMPLETION; + PREG = PREG->u.ld.d; + } + restore_generator_node(SgFr_arity(sg_fr), code_ap); + YENV = (CELL *) PROTECT_FROZEN_B(B); + set_cut(YENV, B->cp_b); + SET_BB(NORM_CP(YENV)); + allocate_environment(); + GONext(); + } +#endif /* INCOMPLETE_TABLING */ + ENDPBOp(); + + + PBOp(table_try_single, ld) tab_ent_ptr tab_ent; sg_fr_ptr sg_fr; check_trail(); tab_ent = PREG->u.ld.te; - sg_fr = subgoal_search(tab_ent, PREG->u.ld.s, &YENV); + sg_fr = subgoal_search(PREG, &YENV); LOCK(SgFr_lock(sg_fr)); if (SgFr_state(sg_fr) == start) { - /* subgoal new or abolished */ + /* subgoal new or not complete (abolished) */ +#ifdef INCOMPLETE_TABLING + ans_node_ptr ans_node = SgFr_first_answer(sg_fr); + if (ans_node) { + /* subgoal not complete --> start by loading the answers already found */ + CELL *subs_ptr = YENV; + init_subgoal_frame(sg_fr); + UNLOCK(SgFr_lock(sg_fr)); + SgFr_try_answer(sg_fr) = ans_node; + store_generator_node(tab_ent, sg_fr, PREG->u.ld.s, TRY_ANSWER); + PREG = (yamop *) CPREG; + PREFETCH_OP(PREG); + load_answer_trie(ans_node, subs_ptr); + YENV = ENV; + GONext(); + } +#endif /* INCOMPLETE_TABLING */ + /* subgoal new */ init_subgoal_frame(sg_fr); UNLOCK(SgFr_lock(sg_fr)); store_generator_node(tab_ent, sg_fr, PREG->u.ld.s, COMPLETION); @@ -364,10 +463,27 @@ check_trail(); tab_ent = PREG->u.ld.te; - sg_fr = subgoal_search(tab_ent, PREG->u.ld.s, &YENV); + sg_fr = subgoal_search(PREG, &YENV); LOCK(SgFr_lock(sg_fr)); if (SgFr_state(sg_fr) == start) { - /* subgoal new or abolished */ + /* subgoal new or not complete (abolished) */ +#ifdef INCOMPLETE_TABLING + ans_node_ptr ans_node = SgFr_first_answer(sg_fr); + if (ans_node) { + /* subgoal not complete --> start by loading the answers already found */ + CELL *subs_ptr = YENV; + init_subgoal_frame(sg_fr); + UNLOCK(SgFr_lock(sg_fr)); + SgFr_try_answer(sg_fr) = ans_node; + store_generator_node(tab_ent, sg_fr, PREG->u.ld.s, TRY_ANSWER); + PREG = (yamop *) CPREG; + PREFETCH_OP(PREG); + load_answer_trie(ans_node, subs_ptr); + YENV = ENV; + GONext(); + } +#endif /* INCOMPLETE_TABLING */ + /* subgoal new */ init_subgoal_frame(sg_fr); UNLOCK(SgFr_lock(sg_fr)); store_generator_node(tab_ent, sg_fr, PREG->u.ld.s, PREG->u.ld.d); @@ -449,10 +565,27 @@ check_trail(); tab_ent = PREG->u.ld.te; - sg_fr = subgoal_search(tab_ent, PREG->u.ld.s, &YENV); + sg_fr = subgoal_search(PREG, &YENV); LOCK(SgFr_lock(sg_fr)); if (SgFr_state(sg_fr) == start) { - /* subgoal new or abolished */ + /* subgoal new or not complete (abolished) */ +#ifdef INCOMPLETE_TABLING + ans_node_ptr ans_node = SgFr_first_answer(sg_fr); + if (ans_node) { + /* subgoal not complete --> start by loading the answers already found */ + CELL *subs_ptr = YENV; + init_subgoal_frame(sg_fr); + UNLOCK(SgFr_lock(sg_fr)); + SgFr_try_answer(sg_fr) = ans_node; + store_generator_node(tab_ent, sg_fr, PREG->u.ld.s, TRY_ANSWER); + PREG = (yamop *) CPREG; + PREFETCH_OP(PREG); + load_answer_trie(ans_node, subs_ptr); + YENV = ENV; + GONext(); + } +#endif /* INCOMPLETE_TABLING */ + /* subgoal new */ init_subgoal_frame(sg_fr); UNLOCK(SgFr_lock(sg_fr)); store_generator_node(tab_ent, sg_fr, PREG->u.ld.s, NEXTOP(PREG,ld)); @@ -1092,7 +1225,7 @@ - BOp(table_completion, ld); + BOp(table_completion, ld) #ifdef YAPOR if (SCH_top_shared_cp(B)) { if (IS_BATCHED_GEN_CP(B)) { @@ -1449,29 +1582,3 @@ } END_PREFETCH() ENDBOp(); - - - - BOp(table_load_answer, ld); - CELL *subs_ptr; - ans_node_ptr ans_node; -#ifdef YAPOR - if (SCH_top_shared_cp(B)) { - PROBLEM: cp_last_answer field is local to the cp! - -> we need a shared data structure to avoid redundant computations! - UNLOCK_OR_FRAME(LOCAL_top_or_fr); - } -#endif /* YAPOR */ - subs_ptr = (CELL *) (LOAD_CP(B) + 1); - ans_node = TrNode_child(LOAD_CP(B)->cp_last_answer); - if(TrNode_child(ans_node) != NULL) { - restore_loader_node(ans_node); - } else { - pop_loader_node(); - } - PREG = (yamop *) CPREG; - PREFETCH_OP(PREG); - load_answer_trie(ans_node, subs_ptr); - YENV = ENV; - GONext(); - ENDBOp(); diff --git a/OPTYap/tab.macros.h b/OPTYap/tab.macros.h index 6ad09525a..8a241cb0e 100644 --- a/OPTYap/tab.macros.h +++ b/OPTYap/tab.macros.h @@ -5,7 +5,7 @@ Copyright: R. Rocha and NCC - University of Porto, Portugal File: tab.macros.h - version: $Id: tab.macros.h,v 1.16 2005-07-26 16:28:28 ricroc Exp $ + version: $Id: tab.macros.h,v 1.17 2005-08-01 15:40:38 ricroc Exp $ **********************************************************************/ @@ -227,23 +227,22 @@ STD_PROTO(static inline tg_sol_fr_ptr CUT_prune_tg_solution_frames, (tg_sol_fr_p memcpy(SuspFr_trail_start(SUSP_FR), SuspFr_trail_reg(SUSP_FR), TR_SIZE) -#define new_subgoal_frame(SG_FR, TAB_ENT, ARITY) \ +#define new_subgoal_frame(SG_FR, CODE) \ { register ans_node_ptr ans_node; \ ALLOC_SUBGOAL_FRAME(SG_FR); \ INIT_LOCK(SgFr_lock(SG_FR)); \ - SgFr_tab_ent(SG_FR) = TAB_ENT; \ - SgFr_arity(SG_FR) = ARITY; \ - new_answer_trie_node(ans_node, 0, 0, NULL, NULL, NULL); \ - SgFr_answer_trie(SG_FR) = ans_node; \ - SgFr_hash_chain(SG_FR) = NULL; \ + SgFr_code(SG_FR) = CODE; \ SgFr_state(SG_FR) = start; \ + new_answer_trie_node(ans_node, 0, 0, NULL, NULL, NULL); \ + SgFr_hash_chain(SG_FR) = NULL; \ + SgFr_answer_trie(SG_FR) = ans_node; \ + SgFr_first_answer(SG_FR) = NULL; \ + SgFr_last_answer(SG_FR) = NULL; \ } #define init_subgoal_frame(SG_FR) \ { SgFr_init_yapor_fields(SG_FR); \ - SgFr_first_answer(SG_FR) = NULL; \ - SgFr_last_answer(SG_FR) = NULL; \ SgFr_state(SG_FR) = evaluating; \ SgFr_next(SG_FR) = LOCAL_top_sg_fr; \ LOCAL_top_sg_fr = sg_fr; \ @@ -518,9 +517,14 @@ void abolish_incomplete_subgoals(choiceptr prune_cp) { LOCAL_top_sg_fr = SgFr_next(sg_fr); LOCK(SgFr_lock(sg_fr)); if (SgFr_first_answer(sg_fr) == SgFr_answer_trie(sg_fr)) { + /* yes answer --> complete */ SgFr_state(sg_fr) = complete; UNLOCK(SgFr_lock(sg_fr)); } else { +#ifdef INCOMPLETE_TABLING + SgFr_state(sg_fr) = start; + UNLOCK(SgFr_lock(sg_fr)); +#else ans_node_ptr node; SgFr_state(sg_fr) = start; free_answer_hash_chain(SgFr_hash_chain(sg_fr)); @@ -532,6 +536,7 @@ void abolish_incomplete_subgoals(choiceptr prune_cp) { UNLOCK(SgFr_lock(sg_fr)); if (node) free_answer_trie_branch(node); +#endif /* INCOMPLETE_TABLING */ } } diff --git a/OPTYap/tab.structs.h b/OPTYap/tab.structs.h index 1ced281bb..3b2fca9ec 100644 --- a/OPTYap/tab.structs.h +++ b/OPTYap/tab.structs.h @@ -5,7 +5,7 @@ Copyright: R. Rocha and NCC - University of Porto, Portugal File: tab.structs.h - version: $Id: tab.structs.h,v 1.8 2005-07-11 19:17:29 ricroc Exp $ + version: $Id: tab.structs.h,v 1.9 2005-08-01 15:40:39 ricroc Exp $ **********************************************************************/ @@ -154,51 +154,59 @@ typedef struct subgoal_frame { int generator_worker; struct or_frame *top_or_frame_on_generator_branch; #endif /* YAPOR */ - struct table_entry *tab_ent; - int subgoal_arity; - choiceptr generator_choice_point; - struct answer_trie_node *answer_trie; - struct answer_trie_node *first_answer; - struct answer_trie_node *last_answer; - struct answer_hash *hash_chain; + yamop *code_of_subgoal; enum { start = 0, evaluating = 1, complete = 2, compiled = 3 } state_flag; + choiceptr generator_choice_point; + struct answer_hash *hash_chain; + struct answer_trie_node *answer_trie; + struct answer_trie_node *first_answer; + struct answer_trie_node *last_answer; +#ifdef INCOMPLETE_TABLING + struct answer_trie_node *try_answer; +#endif /* INCOMPLETE_TABLING */ struct subgoal_frame *next; } *sg_fr_ptr; #define SgFr_lock(X) ((X)->lock) #define SgFr_gen_worker(X) ((X)->generator_worker) #define SgFr_gen_top_or_fr(X) ((X)->top_or_frame_on_generator_branch) -#define SgFr_tab_ent(X) ((X)->tab_ent) -#define SgFr_arity(X) ((X)->subgoal_arity) +#define SgFr_code(X) ((X)->code_of_subgoal) +#define SgFr_tab_ent(X) (((X)->code_of_subgoal)->u.ld.te) +#define SgFr_arity(X) (((X)->code_of_subgoal)->u.ld.s) +#define SgFr_state(X) ((X)->state_flag) #define SgFr_gen_cp(X) ((X)->generator_choice_point) +#define SgFr_hash_chain(X) ((X)->hash_chain) #define SgFr_answer_trie(X) ((X)->answer_trie) #define SgFr_first_answer(X) ((X)->first_answer) #define SgFr_last_answer(X) ((X)->last_answer) -#define SgFr_hash_chain(X) ((X)->hash_chain) -#define SgFr_state(X) ((X)->state_flag) +#define SgFr_try_answer(X) ((X)->try_answer) #define SgFr_next(X) ((X)->next) /* ------------------------------------------------------------------------------------------- ** - SgFr_lock: lock variable to modify the frame fields. + SgFr_lock: spin-lock to modify the frame fields. SgFr_gen_worker: the id of the worker that had allocated the frame. SgFr_gen_top_or_fr: a pointer to the top or-frame in the generator choice point branch. When the generator choice point is shared the pointer is updated to its or-frame. It is used to find the direct dependency node for consumer nodes in other workers branches. + SgFr_code initial instruction of the subgoal's compiled code. SgFr_tab_ent a pointer to the correspondent table entry. SgFr_arity the arity of the subgoal. + SgFr_state: a flag that indicates the subgoal state. SgFr_gen_cp: a pointer to the correspondent generator choice point. + SgFr_hash_chain: a pointer to the first answer_hash struct for the subgoal in hand. SgFr_answer_trie: a pointer to the top answer trie node. It is used to check for/insert new answers. SgFr_first_answer: a pointer to the bottom answer trie node of the first available answer. SgFr_last_answer: a pointer to the bottom answer trie node of the last available answer. - SgFr_hash_chain: a pointer to the first answer_hash struct for the subgoal in hand. - SgFr_state: a flag that indicates the subgoal state. + SgFr_try_answer: a pointer to the bottom answer trie node of the last tried answer. + It is used when a subgoal was not completed during the previous evaluation. + Not completed subgoals start by trying the answers already found. SgFr_next: a pointer to chain between subgoal frames. ** ------------------------------------------------------------------------------------------- */ @@ -298,7 +306,7 @@ struct generator_choicept { struct dependency_frame *cp_dep_fr; /* NULL if batched scheduling */ struct subgoal_frame *cp_sg_fr; #ifdef LOW_LEVEL_TRACER - struct table_entry* cp_tab_ent; + struct pred_entry *cp_pred_entry; #endif /* LOW_LEVEL_TRACER */ }; @@ -306,7 +314,7 @@ struct consumer_choicept { struct choicept cp; struct dependency_frame *cp_dep_fr; #ifdef LOW_LEVEL_TRACER - struct table_entry* cp_tab_ent; + struct pred_entry *cp_pred_entry; #endif /* LOW_LEVEL_TRACER */ }; @@ -314,6 +322,6 @@ struct loader_choicept { struct choicept cp; struct answer_trie_node *cp_last_answer; #ifdef LOW_LEVEL_TRACER - struct table_entry* cp_tab_ent; + struct pred_entry *cp_pred_entry; #endif /* LOW_LEVEL_TRACER */ }; diff --git a/OPTYap/tab.tries.c b/OPTYap/tab.tries.c index 740497495..e36bdf0b0 100644 --- a/OPTYap/tab.tries.c +++ b/OPTYap/tab.tries.c @@ -5,7 +5,7 @@ Copyright: R. Rocha and NCC - University of Porto, Portugal File: tab.tries.C - version: $Id: tab.tries.c,v 1.14 2005-07-11 19:17:29 ricroc Exp $ + version: $Id: tab.tries.c,v 1.15 2005-08-01 15:40:39 ricroc Exp $ **********************************************************************/ @@ -675,12 +675,15 @@ ans_node_ptr answer_trie_node_check_insert(sg_fr_ptr sg_fr, ans_node_ptr parent_ ** Global functions ** ** -------------------------- */ -sg_fr_ptr subgoal_search(tab_ent_ptr tab_ent, OPREG arity, CELL **Yaddr) { - int i, j, count_vars; +sg_fr_ptr subgoal_search(yamop *preg, CELL **Yaddr) { + int i, j, count_vars, arity; CELL *stack_vars, *stack_terms_limit, *stack_terms_base, *stack_terms; sg_node_ptr current_sg_node; + tab_ent_ptr tab_ent; sg_fr_ptr sg_fr; + arity = preg->u.ld.s; + tab_ent = preg->u.ld.te; count_vars = 0; stack_vars = *Yaddr; stack_terms_limit = (CELL *)TR; @@ -747,7 +750,7 @@ sg_fr_ptr subgoal_search(tab_ent_ptr tab_ent, OPREG arity, CELL **Yaddr) { #endif /* TABLE_LOCK_LEVEL */ if (TrNode_sg_fr(current_sg_node) == NULL) { /* new tabled subgoal */ - new_subgoal_frame(sg_fr, tab_ent, arity); + new_subgoal_frame(sg_fr, preg); TrNode_sg_fr(current_sg_node) = (sg_node_ptr) sg_fr; } else { sg_fr = (sg_fr_ptr) TrNode_sg_fr(current_sg_node); @@ -1031,6 +1034,7 @@ void update_answer_trie(sg_fr_ptr sg_fr) { return; } + static struct trie_statistics{ int show; long subgoals; @@ -1048,38 +1052,34 @@ static struct trie_statistics{ int answer_trie_max_depth; int answer_trie_min_depth; } trie_stats; -#define TrStat_show trie_stats.show -#define TrStat_subgoals trie_stats.subgoals -#define TrStat_sg_not_complete trie_stats.subgoals_not_complete -#define TrStat_sg_nodes trie_stats.subgoal_trie_nodes -#define TrStat_sg_linear_nodes trie_stats.subgoal_linear_nodes -#define TrStat_sg_max_depth trie_stats.subgoal_trie_max_depth -#define TrStat_sg_min_depth trie_stats.subgoal_trie_min_depth -#define TrStat_answers trie_stats.answers -#define TrStat_answers_yes trie_stats.answers_yes -#define TrStat_answers_no trie_stats.answers_no -#define TrStat_ans_pruned trie_stats.answers_pruned -#define TrStat_ans_nodes trie_stats.answer_trie_nodes -#define TrStat_ans_linear_nodes trie_stats.answer_linear_nodes -#define TrStat_ans_max_depth trie_stats.answer_trie_max_depth -#define TrStat_ans_min_depth trie_stats.answer_trie_min_depth +#define TrStat_show trie_stats.show +#define TrStat_subgoals trie_stats.subgoals +#define TrStat_sg_not_complete trie_stats.subgoals_not_complete +#define TrStat_sg_nodes trie_stats.subgoal_trie_nodes +#define TrStat_sg_linear_nodes trie_stats.subgoal_linear_nodes +#define TrStat_sg_max_depth trie_stats.subgoal_trie_max_depth +#define TrStat_sg_min_depth trie_stats.subgoal_trie_min_depth +#define TrStat_answers trie_stats.answers +#define TrStat_answers_yes trie_stats.answers_yes +#define TrStat_answers_no trie_stats.answers_no +#define TrStat_ans_pruned trie_stats.answers_pruned +#define TrStat_ans_nodes trie_stats.answer_trie_nodes +#define TrStat_ans_linear_nodes trie_stats.answer_linear_nodes +#define TrStat_ans_max_depth trie_stats.answer_trie_max_depth +#define TrStat_ans_min_depth trie_stats.answer_trie_min_depth #define STR_ARRAY_SIZE 1000 #define ARITY_ARRAY_SIZE 100 -#define SHOW_INFO(MESG, ARGS...) fprintf(Yap_stderr, MESG, ##ARGS) -#define SHOW_TRIE(MESG, ARGS...) if (TrStat_show) fprintf(Yap_stderr, MESG, ##ARGS) +#define SHOW_TABLE(MESG, ARGS...) if (TrStat_show) fprintf(Yap_stderr, MESG, ##ARGS) -void traverse_trie(tab_ent_ptr tab_ent, Atom pred_atom, int show_trie) { - char str[STR_ARRAY_SIZE]; - int arity[ARITY_ARRAY_SIZE]; - int str_index; - int pred_arity = TabEnt_arity(tab_ent); + +int traverse_table(tab_ent_ptr tab_ent, Atom pred_atom, int show_table) { sg_node_ptr sg_node = TrNode_child(TabEnt_subgoal_trie(tab_ent)); - TrStat_show = show_trie; + TrStat_show = show_table; TrStat_subgoals = 0; TrStat_sg_not_complete = 0; - TrStat_sg_nodes = 0; + TrStat_sg_nodes = 1; TrStat_sg_linear_nodes = 0; TrStat_sg_max_depth = -1; TrStat_sg_min_depth = -1; @@ -1091,43 +1091,49 @@ void traverse_trie(tab_ent_ptr tab_ent, Atom pred_atom, int show_trie) { TrStat_ans_linear_nodes = 0; TrStat_ans_max_depth = -1; TrStat_ans_min_depth = -1; - str_index = sprintf(str, " ?- %s(", AtomName(pred_atom)); - arity[0] = 1; - arity[1] = pred_arity; - SHOW_TRIE("\ntable structure for predicate '%s/%d'\n", AtomName(pred_atom), pred_arity); - TrStat_sg_nodes++; - if (sg_node && ! traverse_subgoal_trie(sg_node, str, str_index, arity, 1, TRAVERSE_NORMAL)) - return; - SHOW_INFO("\ntable statistics for predicate '%s/%d'", AtomName(pred_atom), pred_arity); - SHOW_INFO("\n subgoal trie structure"); - SHOW_INFO("\n subgoals: %ld", TrStat_subgoals); - SHOW_INFO("\n subgoals not complete: %ld", TrStat_sg_not_complete); - SHOW_INFO("\n nodes: %ld (%ld%c saving)", - TrStat_sg_nodes, - TrStat_sg_linear_nodes == 0 ? 0 : (TrStat_sg_linear_nodes - TrStat_sg_nodes + 1) * 100 / TrStat_sg_linear_nodes, + if (sg_node) { + char str[STR_ARRAY_SIZE]; + int str_index = sprintf(str, " ?- %s(", AtomName(pred_atom)); + int arity[ARITY_ARRAY_SIZE]; + arity[0] = 1; + arity[1] = TabEnt_arity(tab_ent); + return traverse_subgoal_trie(sg_node, str, str_index, arity, 1, TRAVERSE_NORMAL); + } + SHOW_TABLE(" empty\n"); + return TRUE; +} + + +void table_stats(void) { + fprintf(Yap_stderr, "\n Subgoal trie structure"); + fprintf(Yap_stderr, "\n subgoals: %ld", TrStat_subgoals); + fprintf(Yap_stderr, "\n subgoals not complete: %ld", TrStat_sg_not_complete); + fprintf(Yap_stderr, "\n nodes: %ld (%ld%c saving)", + TrStat_sg_nodes, + TrStat_sg_linear_nodes == 0 ? 0 : (TrStat_sg_linear_nodes - TrStat_sg_nodes + 1) * 100 / TrStat_sg_linear_nodes, + '%'); + fprintf(Yap_stderr, "\n average depth: %.2f (%d min - %d max)", + TrStat_subgoals == 0 ? 0 : (float)TrStat_sg_linear_nodes / (float)TrStat_subgoals, + TrStat_sg_min_depth < 0 ? 0 : TrStat_sg_min_depth, + TrStat_sg_max_depth < 0 ? 0 : TrStat_sg_max_depth); + fprintf(Yap_stderr, "\n Answer trie structure"); + fprintf(Yap_stderr, "\n answers: %ld", TrStat_answers); + fprintf(Yap_stderr, "\n yes answers: %ld", TrStat_answers_yes); + fprintf(Yap_stderr, "\n no answers: %ld", TrStat_answers_no); + fprintf(Yap_stderr, "\n pruned answers: %ld", TrStat_ans_pruned); + fprintf(Yap_stderr, "\n nodes: %ld (%ld%c saving)", + TrStat_ans_nodes, + TrStat_ans_linear_nodes == 0 ? 0 : (TrStat_ans_linear_nodes - TrStat_ans_nodes + TrStat_subgoals) * 100 / TrStat_ans_linear_nodes, '%'); - SHOW_INFO("\n average depth: %.2f (%d min - %d max)", - TrStat_subgoals == 0 ? 0 : (float)TrStat_sg_linear_nodes / (float)TrStat_subgoals, - TrStat_sg_min_depth < 0 ? 0 : TrStat_sg_min_depth, - TrStat_sg_max_depth < 0 ? 0 : TrStat_sg_max_depth); - SHOW_INFO("\n answer trie structure"); - SHOW_INFO("\n answers: %ld", TrStat_answers); - SHOW_INFO("\n yes answers: %ld", TrStat_answers_yes); - SHOW_INFO("\n no answers: %ld", TrStat_answers_no); - SHOW_INFO("\n pruned answers: %ld", TrStat_ans_pruned); - SHOW_INFO("\n nodes: %ld (%ld%c saving)", - TrStat_ans_nodes, - TrStat_ans_linear_nodes == 0 ? 0 : (TrStat_ans_linear_nodes - TrStat_ans_nodes + TrStat_subgoals) * 100 / TrStat_ans_linear_nodes, - '%'); - SHOW_INFO("\n average depth: %.2f (%d min - %d max)", - TrStat_answers == 0 ? 0 : (float)TrStat_ans_linear_nodes / (float)TrStat_answers, - TrStat_ans_min_depth < 0 ? 0 : TrStat_ans_min_depth, - TrStat_ans_max_depth < 0 ? 0 : TrStat_ans_max_depth); - SHOW_INFO("\n total memory in use\n %ld bytes\n\n", - sizeof(struct table_entry) + - TrStat_sg_nodes * sizeof(struct subgoal_trie_node) + - TrStat_ans_nodes * sizeof(struct answer_trie_node) + - TrStat_subgoals * sizeof(struct subgoal_frame)); + fprintf(Yap_stderr, "\n average depth: %.2f (%d min - %d max)", + TrStat_answers == 0 ? 0 : (float)TrStat_ans_linear_nodes / (float)TrStat_answers, + TrStat_ans_min_depth < 0 ? 0 : TrStat_ans_min_depth, + TrStat_ans_max_depth < 0 ? 0 : TrStat_ans_max_depth); + fprintf(Yap_stderr, "\n Total memory in use\n %ld bytes\n", + sizeof(struct table_entry) + + TrStat_sg_nodes * sizeof(struct subgoal_trie_node) + + TrStat_ans_nodes * sizeof(struct answer_trie_node) + + TrStat_subgoals * sizeof(struct subgoal_frame)); return; } @@ -1278,7 +1284,7 @@ int traverse_subgoal_trie(sg_node_ptr sg_node, char *str, int str_index, int *ar arity[arity[0]]++; if (arity[arity[0]] == 0) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str_index += sprintf(& str[str_index], "|"); @@ -1303,7 +1309,7 @@ int traverse_subgoal_trie(sg_node_ptr sg_node, char *str, int str_index, int *ar arity[arity[0]]++; if (arity[arity[0]] == 0) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str_index += sprintf(& str[str_index], "|"); @@ -1350,7 +1356,7 @@ int traverse_subgoal_trie(sg_node_ptr sg_node, char *str, int str_index, int *ar arity[arity[0]]++; if (arity[arity[0]] == 0) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str_index += sprintf(& str[str_index], "|"); @@ -1361,7 +1367,7 @@ int traverse_subgoal_trie(sg_node_ptr sg_node, char *str, int str_index, int *ar if (arity[arity[0]] == -1) { if (strcmp("[]", AtomName(AtomOfTerm(t)))) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str[str_index - 1] = ']'; @@ -1383,7 +1389,7 @@ int traverse_subgoal_trie(sg_node_ptr sg_node, char *str, int str_index, int *ar arity[arity[0]]++; if (arity[arity[0]] == 0) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str_index += sprintf(& str[str_index], "|"); @@ -1430,9 +1436,9 @@ int traverse_subgoal_trie(sg_node_ptr sg_node, char *str, int str_index, int *ar } if (SgFr_state(sg_fr) == start || SgFr_state(sg_fr) == evaluating) { TrStat_sg_not_complete++; - SHOW_TRIE("%s. ---> NOT COMPLETE\n", str); + SHOW_TABLE("%s. ---> NOT COMPLETE\n", str); } else { - SHOW_TRIE("%s.\n", str); + SHOW_TABLE("%s.\n", str); } TrStat_ans_nodes++; if (SgFr_first_answer(sg_fr) == NULL) { @@ -1440,14 +1446,14 @@ int traverse_subgoal_trie(sg_node_ptr sg_node, char *str, int str_index, int *ar TrStat_ans_max_depth = 0; TrStat_ans_min_depth = 0; TrStat_answers_no++; - SHOW_TRIE(" NO ANSWERS\n"); + SHOW_TABLE(" NO ANSWERS\n"); } else if (SgFr_first_answer(sg_fr) == SgFr_answer_trie(sg_fr)) { if (TrStat_ans_max_depth < 0) TrStat_ans_max_depth = 0; TrStat_ans_min_depth = 0; TrStat_answers_yes++; TrStat_answers++; - SHOW_TRIE(" TRUE\n"); + SHOW_TABLE(" TRUE\n"); } else { char answer_str[STR_ARRAY_SIZE]; int answer_arity[ARITY_ARRAY_SIZE]; @@ -1536,7 +1542,7 @@ int traverse_answer_trie(ans_node_ptr ans_node, char *str, int str_index, int *a arity[arity[0]]++; if (arity[arity[0]] == 0) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str_index += sprintf(& str[str_index], "|"); @@ -1563,7 +1569,7 @@ int traverse_answer_trie(ans_node_ptr ans_node, char *str, int str_index, int *a arity[arity[0]]++; if (arity[arity[0]] == 0) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str_index += sprintf(& str[str_index], "|"); @@ -1612,7 +1618,7 @@ int traverse_answer_trie(ans_node_ptr ans_node, char *str, int str_index, int *a arity[arity[0]]++; if (arity[arity[0]] == 0) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str_index += sprintf(& str[str_index], "|"); @@ -1623,7 +1629,7 @@ int traverse_answer_trie(ans_node_ptr ans_node, char *str, int str_index, int *a if (arity[arity[0]] == -1) { if (strcmp("[]", AtomName(AtomOfTerm(t)))) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str[str_index - 1] = ']'; @@ -1645,7 +1651,7 @@ int traverse_answer_trie(ans_node_ptr ans_node, char *str, int str_index, int *a arity[arity[0]]++; if (arity[arity[0]] == 0) { str[str_index] = 0; - SHOW_INFO("%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); + fprintf(Yap_stderr, "%s --> TRIE ERROR: pair without end atom '[]' !!!\n", str); return FALSE; } str_index += sprintf(& str[str_index], "|"); @@ -1680,7 +1686,7 @@ int traverse_answer_trie(ans_node_ptr ans_node, char *str, int str_index, int *a /* show answer .... */ if (IS_ANSWER_LEAF_NODE(ans_node)) { str[str_index] = 0; - SHOW_TRIE("%s\n", str); + SHOW_TABLE("%s\n", str); TrStat_answers++; TrStat_ans_linear_nodes+= depth; if (TrStat_ans_max_depth < 0)