tr_utils.c

00001 /* File:      tr_utils.c
00002 ** Author(s): Prasad Rao, Juliana Freire, Kostis Sagonas
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00006 ** 
00007 ** XSB is free software; you can redistribute it and/or modify it under the
00008 ** terms of the GNU Library General Public License as published by the Free
00009 ** Software Foundation; either version 2 of the License, or (at your option)
00010 ** any later version.
00011 ** 
00012 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00013 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00015 ** more details.
00016 ** 
00017 ** You should have received a copy of the GNU Library General Public License
00018 ** along with XSB; if not, write to the Free Software Foundation,
00019 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 **
00021 ** $Id: tr_utils.c,v 1.116 2006/07/25 14:18:41 tswift Exp $
00022 ** 
00023 */
00024 
00025 
00026 #include "xsb_config.h"
00027 #include "xsb_debug.h"
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 
00033 /* Special debug includes */
00034 #include "debugs/debug_tries.h"
00035 
00036 
00037 #include "auxlry.h"
00038 #include "cell_xsb.h"
00039 #include "cinterf.h"
00040 #include "binding.h"
00041 #include "psc_xsb.h"
00042 #include "heap_xsb.h"
00043 #include "memory_xsb.h"
00044 #include "register.h"
00045 #include "deref.h"
00046 #include "flags_xsb.h"
00047 #include "trie_internals.h"
00048 #include "tst_aux.h"
00049 #include "cut_xsb.h"
00050 #include "macro_xsb.h"
00051 #include "sw_envs.h"
00052 #include "choice.h"
00053 #include "inst_xsb.h"
00054 #include "error_xsb.h"
00055 #include "io_builtins_xsb.h"
00056 #include "trassert.h"
00057 #include "tr_utils.h"
00058 #include "tst_utils.h"
00059 #include "subp.h"
00060 #include "rw_lock.h"
00061 #include "debug_xsb.h"
00062 #include "thread_xsb.h"
00063 #include "storage_xsb.h"
00064 #include "hash_xsb.h"
00065 #include "tables.h"
00066 
00067 /*----------------------------------------------------------------------*/
00068 
00069 #define MAX_VAR_SIZE    200
00070 
00071 #include "ptoc_tag_xsb_i.h"
00072 #include "term_psc_xsb_i.h"
00073 
00074 /*----------------------------------------------------------------------*/
00075 
00076 xsbBool has_unconditional_answers(VariantSF subg)
00077 {
00078   ALNptr node_ptr = subg_answers(subg);
00079  
00080   /* Either subgoal has no answers or it is completed */
00081   /* and its answer list has already been reclaimed. */
00082   /* In either case, the result is immediately obtained. */
00083  
00084 #ifndef CONC_COMPL
00085   if (node_ptr <= COND_ANSWERS) return (node_ptr == UNCOND_ANSWERS);
00086 #else
00087   if (subg_tag(subg) <= COND_ANSWERS) return (subg_tag(subg) == UNCOND_ANSWERS);
00088 #endif
00089  
00090   /* If the subgoal has not been completed, or is early completed but its */
00091   /* answer list has not been reclaimed yet, check each of its nodes. */
00092  
00093   while (node_ptr) {
00094     if (is_unconditional_answer(ALN_Answer(node_ptr))) return TRUE;
00095     node_ptr = ALN_Next(node_ptr);
00096   }
00097   return FALSE;
00098 }
00099 
00100 /*----------------------------------------------------------------------*/
00101 
00102 /* get_call() and supporting code. */
00103 
00104 /*----------------------------------------------------------------------*/
00105 
00106 /*
00107  * Given a subgoal of a variant predicate, returns its subgoal frame
00108  * if it has a table entry; returns NULL otherwise.  If requested, the
00109  * answer template is constructed on the heap as a ret/n term and
00110  * passed back via the last argument.
00111  */
00112 
00113 VariantSF get_variant_sf(CTXTdeclc Cell callTerm, TIFptr pTIF, Cell *retTerm) {
00114 
00115   int arity;
00116   BTNptr root, leaf;
00117   Cell callVars[MAX_VAR_SIZE + 1];
00118 
00119   root = TIF_CallTrie(pTIF);
00120   if ( IsNULL(root) )
00121     return NULL;
00122 
00123   arity = get_arity(TIF_PSC(pTIF));
00124   leaf = variant_trie_lookup(CTXTc root, arity, clref_val(callTerm) + 1, callVars);
00125   if ( IsNULL(leaf) )
00126     return NULL;
00127   if ( IsNonNULL(retTerm) )
00128     *retTerm = build_ret_term(CTXTc callVars[0], &callVars[1]);
00129   return ( CallTrieLeaf_GetSF(leaf) );
00130 }
00131 
00132 /*----------------------------------------------------------------------*/
00133 
00134 /*
00135  * Given a subgoal of a subsumptive predicate, returns the subgoal
00136  * frame of some producing table entry which subsumes it; returns NULL
00137  * otherwise.  The answer template with respect to this producer entry
00138  * is constructed on the heap as a ret/n term and passed back via the
00139  * last argument.
00140  * 
00141  * Note that unlike get_variant_sf, the answer template is derived
00142  * from the subsuming tabled call and the call itself (via
00143  * construct_answer_template), before building the ret_term.
00144  */
00145 
00146 SubProdSF get_subsumer_sf(CTXTdeclc Cell callTerm, TIFptr pTIF, Cell *retTerm) {
00147 
00148   BTNptr root, leaf;
00149   int arity;
00150   TriePathType path_type;
00151   SubProdSF sf;
00152   Cell ansTmplt[MAX_VAR_SIZE + 1];
00153 
00154   root = TIF_CallTrie(pTIF);
00155   if ( IsNULL(root) )
00156     return NULL;
00157 
00158   arity = get_arity(TIF_PSC(pTIF));
00159   leaf = subsumptive_trie_lookup(CTXTc root, arity, clref_val(callTerm) + 1,
00160                                  &path_type, ansTmplt);
00161   if ( IsNULL(leaf) )
00162     return NULL;
00163   sf = (SubProdSF)CallTrieLeaf_GetSF(leaf);
00164   if ( IsProperlySubsumed(sf) ) {
00165     sf = conssf_producer(sf);
00166     construct_answer_template(CTXTc callTerm, sf, ansTmplt);
00167   }
00168   if ( IsNonNULL(retTerm) )
00169     *retTerm = build_ret_term(CTXTc ansTmplt[0], &ansTmplt[1]);
00170   return ( sf );
00171 }
00172   
00173 /*----------------------------------------------------------------------*/
00174 
00175 BTNptr get_trie_root(BTNptr node) {
00176 
00177   while ( IsNonNULL(node) ) {
00178     if ( IsTrieRoot(node) )
00179       return node;
00180     node = BTN_Parent(node);
00181   }
00182   /*
00183    * If the trie is constructed correctly, processing will not reach
00184    * here, other than if 'node' was originally NULL.
00185    */
00186   return NULL;
00187 }
00188 
00189 /*----------------------------------------------------------------------*/
00190 
00191 /*
00192  * Given a vector of terms and their number, N, builds a ret/N structure
00193  * on the heap containing those terms.  Returns this constructed term.
00194  */
00195 
00196 Cell build_ret_term(CTXTdeclc int arity, Cell termVector[]) {
00197 
00198   Pair sym;
00199   CPtr ret_term;
00200   int  i, is_new;
00201 
00202   if ( arity == 0 )
00203     return makestring(get_ret_string());  /* return as a term */
00204   else {
00205     ret_term = hreg;  /* pointer to where ret(..) will be built */
00206     sym = insert("ret", (byte)arity, (Psc)flags[CURRENT_MODULE], &is_new);
00207     new_heap_functor(hreg, pair_psc(sym));
00208     for ( i = 0; i < arity; i++ )
00209       nbldval(termVector[i]);
00210     return makecs(ret_term);  /* return as a term */
00211   }
00212 }
00213 
00214 /*----------------------------------------------------------------------*/
00215 
00216 /*
00217  * Create the answer template for a subsumed call with the given producer.
00218  * The template is stored in an array supplied by the caller.
00219  */
00220 
00221 void construct_answer_template(CTXTdeclc Cell callTerm, SubProdSF producer,
00222                                Cell templ[]) {
00223 
00224   Cell subterm, symbol;
00225   int  sizeAnsTmplt;
00226 
00227   /*
00228    * Store the symbols along the path of the more general call.
00229    */
00230   SymbolStack_ResetTOS;
00231   SymbolStack_PushPath(subg_leaf_ptr(producer));
00232 
00233   /*
00234    * Push the arguments of the subsumed call.
00235    */
00236   TermStack_ResetTOS;
00237   TermStack_PushFunctorArgs(callTerm);
00238 
00239   /*
00240    * Create the answer template while we process.  Since we know we have a
00241    * more general subsuming call, we can greatly simplify the "matching"
00242    * process: we know we either have exact matches of non-variable symbols
00243    * or a variable paired with some subterm of the current call.
00244    */
00245   sizeAnsTmplt = 0;
00246   while ( ! TermStack_IsEmpty ) {
00247     TermStack_Pop(subterm);
00248     XSB_Deref(subterm);
00249     SymbolStack_Pop(symbol);
00250     if ( IsTrieVar(symbol) && IsNewTrieVar(symbol) )
00251       templ[++sizeAnsTmplt] = subterm;
00252     else if ( IsTrieFunctor(symbol) )
00253       TermStack_PushFunctorArgs(subterm)
00254     else if ( IsTrieList(symbol) )
00255       TermStack_PushListArgs(subterm)
00256   }
00257   templ[0] = sizeAnsTmplt;
00258 }
00259 
00260 
00261 /*----------------------------------------------------------------------*/
00262 /*
00263  * Given a term representing a tabled call, determine whether it is
00264  * recorded in the Call Table.  If it is, then return a pointer to its
00265  * subgoal frame and construct on the heap the answer template required
00266  * to retrieve answers for this call.  Place a reference to this term in
00267  * the location pointed to by the second argument.
00268  */
00269 
00270 VariantSF get_call(CTXTdeclc Cell callTerm, Cell *retTerm) {
00271 
00272   Psc  psc;
00273   TIFptr tif;
00274   int arity;
00275   BTNptr root, leaf;
00276   VariantSF sf;
00277   Cell callVars[MAX_VAR_SIZE + 1];
00278 
00279 
00280   psc = term_psc(callTerm);
00281   if ( IsNULL(psc) ) {
00282     err_handle(CTXTc TYPE, 1, "get_call", 3, "callable term", callTerm);
00283     return NULL;
00284   }
00285 
00286   tif = get_tip(CTXTc psc);
00287   if ( IsNULL(tif) )
00288     xsb_abort("Predicate %s/%d is not tabled", get_name(psc), get_arity(psc));
00289 
00290   root = TIF_CallTrie(tif);
00291   if ( IsNULL(root) )
00292     return NULL;
00293 
00294   arity = get_arity(psc);
00295   leaf = variant_trie_lookup(CTXTc root, arity, clref_val(callTerm) + 1, callVars);
00296   if ( IsNULL(leaf) )
00297     return NULL;
00298   else {
00299     sf = CallTrieLeaf_GetSF(leaf);
00300     if ( IsProperlySubsumed(sf) )
00301       construct_answer_template(CTXTc callTerm, conssf_producer(sf), callVars);
00302     *retTerm = build_ret_term(CTXTc callVars[0],&callVars[1]);
00303     return sf;
00304   }
00305 }
00306 
00307 /*======================================================================*/
00308 
00309 /*
00310  *                     D E L E T I N G   T R I E S
00311  *                     ===========================
00312  */
00313 
00314 
00315 /*----------------------------------------------------------------------*/
00316 /* delete_predicate_table(), reclaim_deleted_predicate_table() 
00317  * and supporting code.
00318  * 
00319  * Used to delete/reclaim a predicate-level call and answer trie, works for
00320  * both call-variance and call subsumption. */
00321 /*----------------------------------------------------------------------*/
00322 
00323 /* Stack for top-down traversing and freeing components of a trie
00324    -------------------------------------------------------------- */
00325 
00326 #define freeing_stack_increment 1000
00327 
00328 #define push_node(node) {\
00329   if (node_stk_top >= freeing_stack_size) {\
00330     unsigned long old_freeing_stack_size = freeing_stack_size; \
00331     freeing_stack_size = freeing_stack_size + freeing_stack_increment;\
00332     freeing_stack = (BTNptr *)mem_realloc(freeing_stack,old_freeing_stack_size*sizeof(BTNptr),\
00333                                           freeing_stack_size*sizeof(BTNptr),TABLE_SPACE);\
00334   }\
00335   freeing_stack[node_stk_top] = node;\
00336   node_stk_top++;\
00337   }
00338 
00339 #define pop_node(node) {\
00340   node_stk_top--;\
00341   node = freeing_stack[node_stk_top];\
00342 }
00343 
00344 
00345 /* TLS: since this deallocates from smBTHT, make sure
00346    trie_allocation_type is set to private/shared before using this
00347    function. */
00348 
00349 static void free_trie_ht(CTXTdeclc BTHTptr ht) {
00350 
00351   TrieHT_RemoveFromAllocList(*smBTHT,ht);
00352   mem_dealloc(BTHT_BucketArray(ht),BTHT_NumBuckets(ht)*sizeof(void *),
00353               TABLE_SPACE);
00354   SM_DeallocatePossSharedStruct(*smBTHT,ht); 
00355 }
00356 
00357 /* delete_variant_sf_and_answers deletes and reclaims space for
00358    answers and their subgoal frame in a variant table, and is used by
00359    abolish_table_call.  It copies code from delete_variant_table, but
00360    uses its own stack.  (Not easy to integrate due to macro usage.) */
00361 
00362 /* 
00363  * TLS: since this deallocates from SMs, make sure
00364  * trie_allocation_type is set before using.
00365  */
00366 void delete_variant_sf_and_answers(CTXTdeclc VariantSF pSF) {
00367   int node_stk_top = 0;
00368   BTNptr rnod, *Bkp; 
00369   BTHTptr ht;
00370   
00371   BTNptr *freeing_stack = NULL;
00372   int freeing_stack_size = 0;
00373 
00374   if ( IsNonNULL(subg_ans_root_ptr(pSF)) ) {
00375     push_node((BTNptr)subg_ans_root_ptr(pSF));
00376     while (node_stk_top != 0) {
00377       pop_node(rnod);
00378       if ( IsHashHeader(rnod) ) {
00379         ht = (BTHTptr) rnod;
00380         for (Bkp = BTHT_BucketArray(ht);
00381              Bkp < BTHT_BucketArray(ht) + BTHT_NumBuckets(ht);
00382              Bkp++) {
00383           if ( IsNonNULL(*Bkp) )
00384             push_node(*Bkp);
00385         }
00386         free_trie_ht(CTXTc ht);
00387       }
00388       else {
00389         if (BTN_Sibling(rnod)) 
00390           push_node(BTN_Sibling(rnod));
00391         if ( ! IsLeafNode(rnod) )
00392           push_node(BTN_Child(rnod));
00393         SM_DeallocatePossSharedStruct(*smBTN,rnod);
00394       }
00395     }
00396   } /* free answer trie */
00397   free_answer_list(pSF);
00398   FreeProducerSF(pSF);
00399   mem_dealloc(freeing_stack,freeing_stack_size*sizeof(BTNptr),TABLE_SPACE);
00400 }
00401 
00402 /* 
00403  * TLS: since this deallocates from SMs, make sure
00404  * trie_allocation_type is set before using.
00405  */
00406 static void delete_variant_table(CTXTdeclc BTNptr x) {
00407 
00408   int node_stk_top = 0, call_nodes_top = 0;
00409   BTNptr node, rnod, *Bkp; 
00410   BTHTptr ht;
00411   
00412   BTNptr *freeing_stack = NULL;
00413   int freeing_stack_size = 0;
00414 
00415   if ( IsNULL(x) )
00416     return;
00417 
00418   TRIE_W_LOCK();
00419   push_node(x);
00420   while (node_stk_top > 0) {
00421     pop_node(node);
00422     if ( IsHashHeader(node) ) {
00423       ht = (BTHTptr) node;
00424       for (Bkp = BTHT_BucketArray(ht);
00425            Bkp < BTHT_BucketArray(ht) + BTHT_NumBuckets(ht);
00426            Bkp++) {
00427         if ( IsNonNULL(*Bkp) )
00428           push_node(*Bkp);
00429       }
00430       free_trie_ht(CTXTc ht);
00431     }
00432     else {
00433       if ( IsNonNULL(BTN_Sibling(node)) )
00434         push_node(BTN_Sibling(node));
00435       if ( IsNonNULL(BTN_Child(node)) ) {
00436         if ( IsLeafNode(node) ) {
00440           VariantSF pSF = CallTrieLeaf_GetSF(node);
00441 
00442           /* TLS: this checks whether any answer for this subgoal has
00443           a delay list: may overstate problems but will warn for any
00444           possible corruption. */
00445 
00446           if ( subg_answers(pSF) == COND_ANSWERS ) {
00447             xsb_warn("abolish_table_pred/1 is deleting a table with conditional\
00448                       answers: delay dependencies may be corrupted.\n");
00449           }
00450 
00451           if ( IsNonNULL(subg_ans_root_ptr(pSF)) ) {
00452             call_nodes_top = node_stk_top;
00453             push_node((BTNptr)subg_ans_root_ptr(pSF));
00454             while (node_stk_top != call_nodes_top) {
00455               pop_node(rnod);
00456               if ( IsHashHeader(rnod) ) {
00457                 ht = (BTHTptr) rnod;
00458                 for (Bkp = BTHT_BucketArray(ht);
00459                      Bkp < BTHT_BucketArray(ht) + BTHT_NumBuckets(ht);
00460                      Bkp++) {
00461                   if ( IsNonNULL(*Bkp) )
00462                     push_node(*Bkp);
00463                 }
00464                 free_trie_ht(CTXTc ht);
00465               }
00466               else {
00467                 if (BTN_Sibling(rnod)) 
00468                   push_node(BTN_Sibling(rnod));
00469                 if ( ! IsLeafNode(rnod) )
00470                   push_node(BTN_Child(rnod));
00471                 SM_DeallocateStruct(*smBTN,rnod);
00472               }
00473             }
00474           } /* free answer trie */
00475           free_answer_list(pSF);
00476           FreeProducerSF(pSF);
00477         } /* is leaf */
00478         else 
00479           push_node(BTN_Child(node));
00480       } /* there is a child of "node" */
00481       SM_DeallocateStruct(*smBTN,node);
00482     }
00483   }
00484   TRIE_W_UNLOCK();
00485 
00486   mem_dealloc(freeing_stack,freeing_stack_size*sizeof(BTNptr),TABLE_SPACE);
00487 
00488 }
00489 
00490 void delete_predicate_table(CTXTdeclc TIFptr tif) {
00491   /*  printf("smBTN %x smTableBTN %x private_smTableBTN %x\n",
00492       smBTN, &smTableBTN,private_smTableBTN);
00493       printf("smBTHT %x smTableBTHT %x private_smTableBTHT %x\n",
00494       smBTHT, &smTableBTHT,private_smTableBTHT);*/
00495   if ( TIF_CallTrie(tif) != NULL ) {
00496     if ( IsVariantPredicate(tif) ) {
00497       delete_variant_table(CTXTc TIF_CallTrie(tif));
00498     }
00499     else
00500       delete_subsumptive_table(CTXTc tif);
00501     TIF_CallTrie(tif) = NULL;
00502     TIF_Subgoals(tif) = NULL;
00503   }
00504 }
00505 
00506 /* - - - - - */
00507 
00508 void reclaim_deleted_subsumptive_table(CTXTdeclc DelTFptr);
00509 
00510 void reclaim_deleted_predicate_table(CTXTdeclc DelTFptr deltf_ptr) {
00511 
00512   /*  printf("smBTN %x smTableBTN %x private_smTableBTN %x\n",
00513       smBTN, &smTableBTN,private_smTableBTN);
00514       printf("smBTHT %x smTableBTHT %x private_smTableBTHT %x\n",
00515       smBTHT, &smTableBTHT,private_smTableBTHT);*/
00516 
00517   if ( IsVariantPredicate(subg_tif_ptr(DTF_Subgoals(deltf_ptr))) ) {
00518       delete_variant_table(CTXTc DTF_CallTrie(deltf_ptr));
00519     } else reclaim_deleted_subsumptive_table(CTXTc deltf_ptr);
00520 }
00521 
00522 /*----------------------------------------------------------------------*/
00523 /* delete_branch(), safe_delete_branch(), undelete_branch() and
00524  * supporting code. */
00525 /*----------------------------------------------------------------------*/
00526 
00527  /* 
00528  * Used for call tries (abolish_table_call/1), answer tries (within
00529  * delay handling routines), and by trie_retract.
00530  */
00531 
00532 static int is_hash(BTNptr x) 
00533 {
00534   if( x == NULL)
00535     return(0);
00536   else
00537     return( IsHashHeader(x) );
00538 }
00539 
00540 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00541 
00542 /*
00543  * Set values for "parent" -- the parent node of "current" -- and
00544  * "cur_hook" -- an address containing a pointer into "current"'s level
00545  * in the trie.  If there is no parent node, use the value of
00546  * "root_hook" to find the level.  If the hook is actually contained in
00547  * the parent of current (as its child field), then we've ascended as
00548  * far as we need to go.  Set parent to NULL to indicate this.
00549  */
00550 
00551 static void set_parent_and_node_hook(BTNptr current, BTNptr *root_hook,
00552                                      BTNptr *parent, BTNptr **cur_hook) {
00553 
00554   BTNptr par;
00555 
00556   if ( IsTrieRoot(current) )  /* defend against root having a set parent field */
00557     par = NULL;
00558   else {
00559     par = BTN_Parent(current);
00560     if ( IsNonNULL(par) && (root_hook == &BTN_Child(par)) )
00561       par = NULL;    /* stop ascent when hooking node is reached */
00562   }
00563   if ( IsNULL(par) )
00564     *cur_hook = root_hook;
00565   else
00566     *cur_hook = &BTN_Child(par);
00567   *parent = par;
00568 }
00569 
00570 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00571 
00572 /*
00573  * Given some non-root node which is *not the first* (or only) sibling,
00574  * find the node which precedes it in the chain.  Should ONLY be used
00575  * when deleting trie components.  If a hash table is encountered, then
00576  * its number of contents is decremented.
00577  */
00578 static BTNptr get_prev_sibl(BTNptr node)
00579 {
00580   BTNptr sibling_chain;
00581 
00582   sibling_chain = BTN_Child(BTN_Parent(node));
00583   if ( IsHashHeader(sibling_chain) ) {
00584     BTHTptr ht = (BTHTptr)sibling_chain;
00585     BTHT_NumContents(ht)--;
00586     sibling_chain = *CalculateBucketForSymbol(ht,BTN_Symbol(node));
00587   }
00588   while(sibling_chain != NULL){
00589     if (BTN_Sibling(sibling_chain) == node)
00590       return(sibling_chain);
00591     sibling_chain = BTN_Sibling(sibling_chain);
00592   }  
00593   xsb_abort("Error in get_previous_sibling");
00594   return(NULL);
00595 }
00596 
00597 /*---------------------------------------------------------*/
00598 
00599 /*
00600  * Delete a branch in the trie down from node `lowest_node_in_branch'
00601  * up to the level pointed to by the hook location, as pointed to by
00602  * `hook'.  Under normal use, the "hook" is either for the root of the
00603  * trie, or for the first level of the trie (is a pointer to the child
00604  * field of the root).  */
00605 
00606 /* 
00607  * TLS: since this deallocates from SMs, make sure
00608  * trie_allocation_type is set before using.
00609  */
00610 void delete_branch(CTXTdeclc BTNptr lowest_node_in_branch, BTNptr *hook) {
00611 
00612   int num_left_in_hash;
00613   BTNptr prev, parent_ptr, *y1, *z;
00614 
00615 
00616   while ( IsNonNULL(lowest_node_in_branch) && 
00617           ( Contains_NOCP_Instr(lowest_node_in_branch) ||
00618             IsTrieRoot(lowest_node_in_branch) ) ) {
00619     /*
00620      *  Walk up a path with no branches, i.e., the nodes along this path
00621      *  have no siblings.  We know this because the instruction in the
00622      *  node is of the no_cp variety.
00623      */
00624     set_parent_and_node_hook(lowest_node_in_branch,hook,&parent_ptr,&y1);
00625     if (is_hash(*y1)) {
00626       z = CalculateBucketForSymbol((BTHTptr)(*y1),
00627                                    BTN_Symbol(lowest_node_in_branch));
00628       if ( *z != lowest_node_in_branch )
00629         xsb_dbgmsg((LOG_DEBUG,"DELETE_BRANCH: trie node not found in hash table"));
00630       *z = NULL;
00631       num_left_in_hash = --BTHT_NumContents((BTHTptr)*y1);
00632       if (num_left_in_hash  > 0) {
00633         /*
00634          * `lowest_node_in_branch' has siblings, even though they are not in
00635          * the same chain.  Therefore we cannot delete the parent, and so
00636          * we're done.
00637          */
00638         SM_DeallocateStruct(*smBTN,lowest_node_in_branch);
00639         return;
00640       }
00641       else
00642         free_trie_ht(CTXTc (BTHTptr)(*y1));
00643     }
00644     /*
00645      *  Remove this node and continue.
00646      */
00647     SM_DeallocateStruct(*smBTN,lowest_node_in_branch);
00648     lowest_node_in_branch = parent_ptr;
00649   }
00650 
00651   if (lowest_node_in_branch == NULL)
00652     *hook = 0;
00653   else {
00654     if (Contains_TRY_Instr(lowest_node_in_branch)) {
00655       /* Alter sibling's instruction:  trust -> no_cp  retry -> try */
00656       BTN_Instr(BTN_Sibling(lowest_node_in_branch)) =
00657         BTN_Instr(BTN_Sibling(lowest_node_in_branch)) -1;
00658       y1 = &BTN_Child(BTN_Parent(lowest_node_in_branch));
00659       if (is_hash(*y1)) {
00660         z = CalculateBucketForSymbol((BTHTptr)(*y1),
00661                                      BTN_Symbol(lowest_node_in_branch));
00662         num_left_in_hash = --BTHT_NumContents((BTHTptr)*y1);
00663       }
00664       else
00665         z = y1;
00666       *z = BTN_Sibling(lowest_node_in_branch);      
00667     }
00668     else { /* not the first in the sibling chain */
00669       prev = get_prev_sibl(lowest_node_in_branch);      
00670       BTN_Sibling(prev) = BTN_Sibling(lowest_node_in_branch);
00671       if (Contains_TRUST_Instr(lowest_node_in_branch))
00672         BTN_Instr(prev) -= 2; /* retry -> trust ; try -> nocp */
00673     }
00674     SM_DeallocateStruct(*smBTN,lowest_node_in_branch);
00675   }
00676 }
00677 
00678 /*------------------------------*/
00679 
00680 void safe_delete_branch(BTNptr lowest_node_in_branch) {
00681 
00682   byte choicepttype;
00683 
00684   MakeStatusDeleted(lowest_node_in_branch);
00685   choicepttype = 0x3 & BTN_Instr(lowest_node_in_branch);
00686   BTN_Instr(lowest_node_in_branch) = choicepttype | trie_no_cp_fail;
00687 }
00688 
00689 void undelete_branch(BTNptr lowest_node_in_branch) {
00690 
00691    byte choicepttype; 
00692    byte typeofinstr;
00693 
00694    if( IsDeletedNode(lowest_node_in_branch) ){
00695      choicepttype = 0x3 &  BTN_Instr(lowest_node_in_branch);
00696      /* Status contains the original instruction that was in that trie node.
00697         here we extract the original instruction and the next statement
00698         makes it into the instruction associated with that node. */
00699      typeofinstr = (~0x3) & BTN_Status(lowest_node_in_branch);
00700 
00701      BTN_Instr(lowest_node_in_branch) = choicepttype | typeofinstr;
00702      /* This only sets the status field. It is also necessary to set the
00703         instruction field correctly, which is done above. */
00704      MakeStatusValid(lowest_node_in_branch);
00705    }
00706    else
00707      /* This is permitted, because we might bt_delete, then insert
00708         (non-backtrackably) and then backtrack.
00709      */
00710      xsb_dbgmsg((LOG_INTERN, "Undeleting a node that is not deleted"));
00711 }
00712 
00713 
00714 /*----------------------------------------------------------------------*/
00715 /* delete_trie() and supporting code.  
00716  * 
00717  * Code to support deletion of asserted or interned tries.
00718  * delete_trie() is used by gen_retractall (i.e. abolish or retractall
00719  * with an open atomic formula) to delete an entire asserted trie.
00720  * Its also called via the builtin DELETE_TRIE --
00721  * delete_interned_trie() to delete an interned trie or storage trie */
00722 /*----------------------------------------------------------------------*/
00723 
00724 #define DELETE_TRIE_STACK_INIT 100
00725 #define MAX_DELETE_TRIE_STACK_SIZE 1000
00726 #define DT_NODE 0
00727 #define DT_DS 1
00728 #define DT_HT 2
00729 
00730 #define push_delete_trie_node(node,op) {\
00731   trie_op_top++;\
00732   if (trie_op_top >= trie_op_size) {\
00733     trie_op_size = 2*trie_op_size;\
00734     delete_trie_op = (char *)mem_realloc(delete_trie_op,(trie_op_size/2)*sizeof(char),trie_op_size*sizeof(char),TABLE_SPACE);\
00735     if (!delete_trie_op) xsb_exit("out of space for deleting trie");\
00736     /*xsb_dbgmsg((LOG_DEBUG,"realloc delete_trie_op to %d",trie_op_size));*/\
00737   }\
00738   delete_trie_op[trie_op_top] = op;\
00739   trie_node_top++;\
00740   if (trie_node_top >= trie_node_size) {\
00741     trie_node_size = 2*trie_node_size;\
00742     delete_trie_node = (BTNptr *)mem_realloc(delete_trie_node,(trie_node_size/2)*sizeof(BTNptr),trie_node_size*sizeof(BTNptr),TABLE_SPACE);\
00743     if (!delete_trie_node) xsb_exit("out of space for deleting trie");\
00744     /*xsb_dbgmsg((LOG_DEBUG,"realloc delete_trie_node to %d",trie_node_size));*/\
00745   }\
00746   delete_trie_node[trie_node_top] = node;\
00747 }  
00748 #define push_delete_trie_hh(hh) {\
00749   trie_op_top++;\
00750   if (trie_op_top >= trie_op_size) {\
00751     trie_op_size = 2*trie_op_size;\
00752     delete_trie_op = (char *)mem_realloc(delete_trie_op,(trie_op_size/2)*sizeof(char),trie_op_size*sizeof(char),TABLE_SPACE);\
00753     if (!delete_trie_op) xsb_exit("out of space for deleting trie");\
00754     /*xsb_dbgmsg((LOG_DEBUG,"realloc delete_trie_op to %d",trie_op_size));*/\
00755   }\
00756   delete_trie_op[trie_op_top] = DT_HT;\
00757   trie_hh_top++;\
00758   if (trie_hh_top >= trie_hh_size) {\
00759     trie_hh_size = 2*trie_hh_size;\
00760     delete_trie_hh = (BTHTptr *)mem_realloc(delete_trie_hh,(trie_hh_size/2)*sizeof(BTHTptr),trie_hh_size*sizeof(BTHTptr),TABLE_SPACE);\
00761     if (!delete_trie_hh) xsb_exit("out of space for deleting trie");\
00762     /*xsb_dbgmsg((LOG_DEBUG,"realloc delete_trie_hh to %d",trie_hh_size));*/\
00763   }\
00764   delete_trie_hh[trie_hh_top] = hh;\
00765 }  
00766 
00767 /*************************************************************************/
00768 /* TLS: assumed for the purpose of MT storage managers, that
00769    delete_trie() is being called only to delete asserted tries --
00770    otherwise, need to set smBTN and smBTHT to private/shared */
00771 
00772 void delete_trie(CTXTdeclc BTNptr iroot) {
00773 
00774   BTNptr root, sib, chil;  
00775   int trie_op_top = 0;
00776   int trie_node_top = 0;
00777   int trie_hh_top = -1;
00778 
00779   char *delete_trie_op = NULL;
00780   BTNptr *delete_trie_node = NULL;
00781   BTHTptr *delete_trie_hh = NULL;
00782   int trie_op_size, trie_node_size, trie_hh_size;
00783 
00784   if (!delete_trie_op) {
00785     delete_trie_op = (char *)mem_alloc(DELETE_TRIE_STACK_INIT*sizeof(char),TABLE_SPACE);
00786     delete_trie_node = (BTNptr *)mem_alloc(DELETE_TRIE_STACK_INIT*sizeof(BTNptr),TABLE_SPACE);
00787     delete_trie_hh = (BTHTptr *)mem_alloc(DELETE_TRIE_STACK_INIT*sizeof(BTHTptr),TABLE_SPACE);
00788     trie_op_size = trie_node_size = trie_hh_size = DELETE_TRIE_STACK_INIT;
00789   }
00790 
00791   delete_trie_op[0] = 0;
00792   delete_trie_node[0] = iroot;
00793   while (trie_op_top >= 0) {
00794     /*    xsb_dbgmsg((LOG_DEBUG,"top %d %d %d %p",trie_op_top,trie_hh_top,
00795           delete_trie_op[trie_op_top],delete_trie_node[trie_node_top])); */
00796     switch (delete_trie_op[trie_op_top--]) {
00797     case DT_DS:
00798       root = delete_trie_node[trie_node_top--];
00799       SM_DeallocateStruct(*smBTN,root);
00800       break;
00801     case DT_HT:
00802       free_trie_ht(CTXTc delete_trie_hh[trie_hh_top--]);
00803       break;
00804     case DT_NODE:
00805       root = delete_trie_node[trie_node_top--];
00806       if ( IsNonNULL(root) ) {
00807         if ( IsHashHeader(root) ) {
00808           BTHTptr hhdr;
00809           BTNptr *base, *cur;
00810           hhdr = (BTHTptr)root;
00811           base = BTHT_BucketArray(hhdr);
00812           push_delete_trie_hh(hhdr);
00813           for ( cur = base; cur < base + BTHT_NumBuckets(hhdr); cur++ ) {
00814             if (IsNonNULL(*cur)) {
00815               push_delete_trie_node(*cur,DT_NODE);
00816             }
00817           }
00818         }
00819         else {
00820           sib  = BTN_Sibling(root);
00821           chil = BTN_Child(root);      
00822           /* Child nodes == NULL is not the correct test*/
00823           if (IsLeafNode(root)) {
00824             if (IsNonNULL(chil))
00825               xsb_exit("Anomaly in delete_trie !");
00826             push_delete_trie_node(root,DT_DS);
00827             if (IsNonNULL(sib)) {
00828               push_delete_trie_node(sib,DT_NODE);
00829             }
00830           }
00831           else {
00832             push_delete_trie_node(root,DT_DS);
00833             if (IsNonNULL(sib)) {
00834               push_delete_trie_node(sib,DT_NODE);
00835             }
00836             if (IsNonNULL(chil)) {
00837               push_delete_trie_node(chil,DT_NODE);
00838             }
00839           }
00840         }
00841       } else
00842         printf("null node");
00843       break;
00844     }
00845   }
00846   mem_dealloc(delete_trie_op,trie_op_size,TABLE_SPACE); delete_trie_op = NULL;
00847   mem_dealloc(delete_trie_node,trie_node_size,TABLE_SPACE); delete_trie_node = NULL;
00848   mem_dealloc(delete_trie_hh,trie_hh_size,TABLE_SPACE); delete_trie_hh = NULL;
00849   trie_op_size = 0; 
00850 }
00851 
00852 /*======================================================================*/
00853 
00854 /*
00855  *                  A N S W E R   O P E R A T I O N S
00856  *                  =================================
00857  */
00858 
00859 /*----------------------------------------------------------------------*/
00860 
00861 /*
00862  * This does not reclaim space for deleted nodes, only marks
00863  * the node as deleted and changes the try instruction to fail.
00864  * The deleted node is then linked into the del_nodes_list
00865  * in the completion stack.
00866  * 
00867  * TLS: I have a question about the simplification done at the end of
00868  * this predicate.  It should only be performed if the trie is completed.
00869  * 
00870  * TLS: put in some protection for simplification operations using
00871  * MUTEX_DELAY.  But I'm not sure that other parts of this function
00872  * are thread-safe.
00873  */
00874 void delete_return(CTXTdeclc BTNptr l, VariantSF sg_frame) 
00875 {
00876   ALNptr a, n, next;
00877   NLChoice c;
00878   int groundcall = FALSE;
00879 #ifdef LOCAL_EVAL
00880   TChoice  tc;
00881 #endif
00882 
00883     xsb_dbgmsg((LOG_INTERN, "DELETE_NODE: %d - Par: %d", l, BTN_Parent(l)));
00884 
00885     /* deleting an answer makes it false, so we have to deal with 
00886        delay lists */
00887     if (is_conditional_answer(l)) {
00888       ASI asi = Delay(l);
00889       SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00890       release_all_dls(asi);
00891       SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00892       /* TLS 12/00 changed following line from 
00893          (l == subg_ans_root_ptr(sg_frame) && ..
00894          so that negation failure simplification is properly performed */
00895       if (l == BTN_Child(subg_ans_root_ptr(sg_frame)) &&
00896           IsEscapeNode(l))
00897         groundcall=TRUE; /* do it here, when l is still valid */
00898     }
00899 
00900   if (is_completed(sg_frame)) {
00901     safe_delete_branch(l);
00902   } else {
00903     SET_TRIE_ALLOCATION_TYPE_SF(sg_frame);
00904     delete_branch(CTXTc l,&subg_ans_root_ptr(sg_frame));
00905     n = subg_ans_list_ptr(sg_frame);
00906     /* Find previous sibling -pvr */
00907     while (ALN_Answer(ALN_Next(n)) != l) {
00908       n = ALN_Next(n);/* if a is not in that list a core dump will result */
00909     }
00910     if (n == NULL) {
00911       xsb_exit("Error in delete_return()");
00912     }
00913     a               = ALN_Next(n);
00914     next            = ALN_Next(a);
00915     ALN_Answer(a)   = NULL; /* since we eagerly release trie nodes, this is
00916                                necessary to keep garbage collection sane */
00917     ALN_Next(a) = compl_del_ret_list(subg_compl_stack_ptr(sg_frame));
00918     compl_del_ret_list(subg_compl_stack_ptr(sg_frame)) = a;    
00919 
00920     ALN_Next(n) = next;
00921     
00922     /* Make consumed answer field of consumers point to
00923        previous sibling if they point to a deleted answer */
00924     c = (NLChoice) subg_asf_list_ptr(sg_frame);
00925     while(c != NULL){
00926       if(nlcp_trie_return(c) == a){
00927         nlcp_trie_return(c) = n;
00928       }
00929       c = (NLChoice)nlcp_prevlookup(c);
00930     }
00931 
00932 #if (defined(LOCAL_EVAL))
00933       /* if gen-cons points to deleted answer, make it
00934        * point to previous sibling */
00935       tc = (TChoice)subg_cp_ptr(sg_frame);
00936       if (tcp_trie_return(tc) == a) {
00937         tcp_trie_return(tc) = n;
00938       }
00939 #endif
00940    
00941     ALN_Next(n) = next;
00942 
00943     if(next == NULL){ /* last answer */
00944       subg_ans_list_tail(sg_frame) = n;
00945     }      
00946   }
00947   if (is_conditional_answer(l)) {
00948     SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00949     simplify_pos_unsupported(CTXTc l);
00950     if (groundcall) {
00951       mark_subgoal_failed(sg_frame);
00952       simplify_neg_fails(CTXTc sg_frame);
00953     }
00954     SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00955   }
00956 }
00957 
00958 /*----------------------------------------------------------------------*/
00959 /* Given a tabled subgoal, go through its list of deleted nodes (in the
00960  * completion stack), and reclaim the leaves and corresponding branches
00961  *----------------------------------------------------------------------*/
00962 
00963 void  reclaim_del_ret_list(CTXTdeclc VariantSF sg_frame) {
00964   ALNptr x,y;
00965   
00966   x = compl_del_ret_list(subg_compl_stack_ptr(sg_frame));
00967   
00968   while (x != NULL) {
00969     y = x;
00970     x = ALN_Next(x);
00971 /*      delete_branch(ALN_Answer(y), &subg_ans_root_ptr(sg_frame)); */
00972 #ifndef MULTI_THREAD
00973     SM_DeallocateStruct(smALN,y);
00974 #else
00975    if (IsSharedSF(sg_frame)) {                  
00976      SM_DeallocateSharedStruct(smALN,y);
00977    } else {
00978      SM_DeallocateStruct(*private_smALN,y);
00979    }
00980 #endif
00981   }
00982 }
00983  
00984 /*----------------------------------------------------------------------*/
00985 
00986 /*
00987 **   Used in aggregs.P to implement aggregates.
00988 **   Takes:   breg (the place where choice point is saved) and arity.  
00989 **   Returns: subgoal skeleton (i.e., ret(X,Y,Z), where X,Y,Z are all the 
00990 **                              distinct variables in the subgoal);
00991 **            Pointer to the subgoal.
00992 */
00993 
00994 void breg_retskel(CTXTdecl)
00995 {
00996     Pair    sym;
00997     Cell    term;
00998     VariantSF sg_frame;
00999     CPtr    tcp, cptr, where;
01000     int     is_new, i;
01001     Integer breg_offset, Nvars;
01002 
01003     breg_offset = ptoc_int(CTXTc 1);
01004     tcp = (CPtr)((Integer)(tcpstack.high) - breg_offset);
01005     sg_frame = (VariantSF)(tcp_subgoal_ptr(tcp));
01006     where = tcp_template(tcp);
01007     Nvars = int_val(cell(where)) & 0xffff;
01008     cptr = where - Nvars - 1;
01009     if (Nvars == 0) {
01010       ctop_string(CTXTc 3, get_ret_string());
01011     } else {
01012       bind_cs((CPtr)ptoc_tag(CTXTc 3), hreg);
01013       sym = insert("ret", (byte)Nvars, (Psc)flags[CURRENT_MODULE], &is_new);
01014       new_heap_functor(hreg, sym->psc_ptr);
01015       for (i = Nvars; i > 0; i--) {
01016         term = (Cell)(*(CPtr)(cptr+i));
01017         nbldval(term);
01018       }
01019     }
01020     ctop_int(CTXTc 4, (Integer)sg_frame);
01021 }
01022 
01023 
01024 /*======================================================================*/
01025 
01026 /*
01027  *                    I N T E R N E D   T R I E S
01028  *                    ===========================
01029  */
01030 
01031 #define ADJUST_SIZE 100
01032 
01033 #ifndef MULTI_THREAD
01034 BTNptr *Set_ArrayPtr;
01035 /*
01036  * first_free_set is the index of the first deleted set.  The deleted
01037  * tries are deleted in builtin DELETE_TRIE, and the corresponding
01038  * elements in Set_ArrayPtr are linked to form a list.  So
01039  * Set_ArrayPtr[first_free_set] contains the index of the next deleted
01040  * set, ..., the last one contains 0.  If first_free_set == 0, that
01041  * means no free set available.
01042  */
01043 Integer first_free_set;
01044 int Set_ArraySz;
01045 /*
01046  * num_sets is the number of sets have been used (including the fixed
01047  * trie, Set_ArrayPtr[0] (see trie_intern/3)).  It is also the index for
01048  * the next element to use when no free element is available.
01049  */
01050 int num_sets;
01051 #endif
01052 
01053 /*----------------------------------------------------------------------*/
01054 
01055 /* Allocate an array of handles to interned tries, and initialize
01056    global variables. */
01057 
01058 void init_newtrie(CTXTdecl)
01059 {
01060   first_free_set = 0;
01061   Set_ArraySz = 10;  /* must be at least num_sets */
01062   num_sets = 1;
01063   Set_ArrayPtr = (BTNptr *) mem_calloc(Set_ArraySz,sizeof(BTNptr),TABLE_SPACE);
01064 
01065   bt_storage_hash_table.length = STORAGE_TBL_SIZE;
01066   bt_storage_hash_table.bucket_size = sizeof(STORAGE_HANDLE);
01067   bt_storage_hash_table.initted = FALSE;
01068   bt_storage_hash_table.table = NULL;
01069 }
01070 
01071 /*----------------------------------------------------------------------*/
01072 
01073 /* Returns a handle to an unused interned trie. */
01074 
01075 Integer newtrie(CTXTdecl)
01076 {
01077   Integer i;
01078   Integer result;
01079   
01080   if (first_free_set != 0) {    /* a free set is available */
01081     i = first_free_set;         /* save it in i */
01082     result = first_free_set;
01083     first_free_set = (Integer) Set_ArrayPtr[first_free_set] >> 2;
01084     Set_ArrayPtr[i] = NULL;     /* must be reset to NULL */
01085   }
01086   else {
01087     if (num_sets == Set_ArraySz) { /* run out of elements */
01088       BTNptr *temp_arrayptr;
01089       unsigned long temp_arraysz;
01090 
01091       temp_arrayptr = Set_ArrayPtr;
01092       temp_arraysz = Set_ArraySz;
01093       Set_ArraySz += ADJUST_SIZE;  /* adjust the array size */
01094       Set_ArrayPtr = (BTNptr *) mem_calloc(Set_ArraySz ,sizeof(BTNptr),TABLE_SPACE);
01095       if (Set_ArrayPtr == NULL)
01096         xsb_exit("Out of memory in new_trie/1");
01097       for (i = 0; i < num_sets; i++)
01098         Set_ArrayPtr[i] = temp_arrayptr[i];
01099       mem_dealloc(temp_arrayptr,temp_arraysz,TABLE_SPACE);
01100     }
01101     result = (Integer)num_sets;
01102     num_sets++;
01103   }
01104   return result;
01105 }
01106 
01107 /*----------------------------------------------------------------------*/
01108 
01109 void trie_intern(CTXTdecl)
01110 {
01111   prolog_term term;
01112   int RootIndex;
01113   int flag;
01114   BTNptr Leaf;
01115 
01116   term = ptoc_tag(CTXTc 1);
01117   RootIndex = ptoc_int(CTXTc 2);
01118 
01119   xsb_dbgmsg((LOG_INTERN, "Interning "));
01120   dbg_printterm(LOG_INTERN,stddbg,term,25);
01121   xsb_dbgmsg((LOG_INTERN, "In trie with root %d", RootIndex));
01122 
01123   switch_to_trie_assert;
01124   Leaf = whole_term_chk_ins(CTXTc term,&(Set_ArrayPtr[RootIndex]),&flag);
01125   switch_from_trie_assert;
01126   
01127   ctop_int(CTXTc 3,(Integer)Leaf);
01128   ctop_int(CTXTc 4,flag);
01129   xsb_dbgmsg((LOG_INTERN, "Exit flag %d",flag));
01130 }
01131 
01132 /*----------------------------------------------------------------------*/
01133 
01134 int trie_interned(CTXTdecl)
01135 {
01136   int RootIndex;
01137   int ret_val = FALSE;
01138   Cell Leafterm, trie_term;
01139 #ifdef MULTI_THREAD_RWL
01140    CPtr tbreg;
01141 #ifdef SLG_GC
01142    CPtr old_cptop;
01143 #endif
01144 #endif
01145 
01146   trie_term =  ptoc_tag(CTXTc 1);
01147   RootIndex = ptoc_int(CTXTc 2);
01148   Leafterm = ptoc_tag(CTXTc 3);
01149   
01150   /*
01151    * Only if Set_ArrayPtr[RootIndex] is a valid BTNptr can we run this
01152    * builtin.  That means Set_ArrayPtr[RootIndex] can neither be NULL,
01153    * nor a deleted set (deleted by builtin delete_trie/1).
01154    */
01155   if ((Set_ArrayPtr[RootIndex] != NULL) &&
01156       (!((long) Set_ArrayPtr[RootIndex] & 0x3))) {
01157     XSB_Deref(trie_term);
01158     XSB_Deref(Leafterm);
01159     if ( isref(Leafterm) ) {  
01160       reg_arrayptr = reg_array -1;
01161       num_vars_in_var_regs = -1;
01162       pushreg(trie_term);
01163 #ifdef MULTI_THREAD_RWL
01164 /* save choice point for trie_unlock instruction */
01165        save_find_locx(ereg);
01166        tbreg = top_of_cpstack;
01167 #ifdef SLG_GC
01168        old_cptop = tbreg;
01169 #endif
01170        save_choicepoint(tbreg,ereg,(byte *)&trie_fail_unlock_inst,breg);
01171 #ifdef SLG_GC
01172        cp_prevtop(tbreg) = old_cptop;
01173 #endif
01174        breg = tbreg;
01175        hbreg = hreg;
01176 #endif
01177       pcreg = (byte *)Set_ArrayPtr[RootIndex];
01178       ret_val =  TRUE;
01179     }
01180     else{
01181       xsb_instantiation_error(CTXTc "trie_interned",4,3,"non-attributed and non-ground");
01182     }
01183   }
01184   return(ret_val);
01185 }
01186 
01187 /*----------------------------------------------------------------------*/
01188 
01189 /*
01190  * This is builtin #162: TRIE_DISPOSE(+ROOT, +LEAF), to dispose a branch
01191  * of the trie rooted at Set_ArrayPtr[ROOT].
01192  */
01193 
01194 void trie_dispose(CTXTdecl)
01195 {
01196   BTNptr Leaf;
01197   long Rootidx;
01198 
01199   Rootidx = ptoc_int(CTXTc 1);
01200   Leaf = (BTNptr)ptoc_int(CTXTc 2);
01201   switch_to_trie_assert;
01202   delete_branch(CTXTc Leaf, &(Set_ArrayPtr[Rootidx]));
01203   switch_from_trie_assert;
01204 }
01205 
01206 /*----------------------------------------------------------------------*/
01207 
01208 #define DELETED_SET 1
01209 
01210 void delete_interned_trie(CTXTdeclc Integer tmpval) {
01211   /*
01212    * We can only delete a valid BTNptr, so that only those sets
01213    * that were used before can be put into the free set list.
01214    */
01215   if ((Set_ArrayPtr[tmpval] != NULL) &&
01216       (!((Integer) Set_ArrayPtr[tmpval] & 0x3))) {
01217     switch_to_trie_assert;
01218     delete_trie(CTXTc Set_ArrayPtr[tmpval]);
01219     switch_from_trie_assert;
01220     /*
01221      * Save the value of first_free_set into Set_ArrayPtr[tmpval].
01222      * Some simple encoding is needed, because in trie_interned/4 we
01223      * have to know this set is already deleted.
01224      */
01225     Set_ArrayPtr[tmpval] = (BTNptr) (first_free_set << 2 | DELETED_SET);
01226     first_free_set = tmpval;
01227   }
01228 }
01229 
01230 
01231 /*  
01232  Changes made by Prasad Rao. Jun 20th 2000
01233 
01234  The solution for reclaiming the garbage nodes resulting
01235  from trie dispose is as follows.
01236  Maintain a datastructure as follows
01237  1)  IGRhead -> Root1 -> Root2 -> Root3 -> null
01238                  |        |        |
01239                  |        |        |
01240                  v        v        v
01241                 Leaf11   Leaf21   Leaf31
01242                  |        |        |  
01243                  |        |        |
01244                  V        v        v
01245                 Leaf12    null    Leaf32        
01246                  |                 |
01247                  v                 |
01248                 null               v
01249                                  Leaf33
01250                                    |
01251                                    v
01252                                   null
01253 To reclaim all the garbage associated with a particular root
01254  a) remove the root from the root list
01255  b) remove all the garbage branches assoc with the root 
01256     by calling delete_branch(leaf,....)
01257    Done!!
01258 
01259 */
01260 
01261 #ifndef MULTI_THREAD
01262 static IGRptr IGRhead = NULL;
01263 #endif
01264 
01265 static IGRptr newIGR(long root)
01266 {
01267   IGRptr igr;
01268   
01269   igr = (IGRptr) mem_alloc(sizeof(InternGarbageRoot),TABLE_SPACE);
01270   igr -> root   = root;
01271   igr -> leaves = NULL;
01272   igr -> next   = NULL;
01273   return igr;
01274 }
01275 
01276 static IGLptr newIGL(BTNptr leafn)
01277 {
01278   IGLptr igl;
01279   
01280   igl = (IGLptr) mem_alloc(sizeof(InternGarbageLeaf),TABLE_SPACE);
01281   igl -> leaf = leafn;
01282   igl -> next = NULL;
01283   return igl;
01284 }
01285 
01286 static IGRptr getIGRnode(CTXTdeclc long rootn)
01287 {
01288   IGRptr p = IGRhead;  
01289 
01290   while(p != NULL){
01291     if(p -> root == rootn)
01292       return p;
01293     else
01294       p = p -> next;
01295   }  
01296   if(p != NULL)
01297     xsb_warn("Invariant p == NULL violated");
01298 
01299   p = newIGR(rootn);
01300   p -> next = IGRhead;
01301   IGRhead = p;    
01302   return p;
01303 }
01304 
01305 static IGRptr getAndRemoveIGRnode(CTXTdeclc long rootn)
01306 {
01307   IGRptr p = IGRhead;  
01308 
01309   if(p == NULL)
01310     return NULL;
01311   else if(p -> root == rootn){
01312     IGRhead = p -> next;
01313     return p;
01314   }
01315   else{
01316     IGRptr q = p;
01317     p = p -> next;
01318     while(p != NULL){
01319       if(p -> root == rootn){
01320         q -> next = p -> next;
01321         return p;
01322       } else{
01323         q = p;
01324         p = p -> next;
01325       }
01326     }  
01327   }
01328   xsb_dbgmsg((LOG_INTERN, "Root node not found in Garbage List"));
01329   return NULL;
01330 }
01331 
01332 
01333 
01334 /*
01335  *  Insert "leafn" into the garbage list, "r".
01336  *  This is done when leafn is deleted so that we could undelete it or later
01337  *  garbage-collect it.
01338  */
01339 static void insertLeaf(IGRptr r, BTNptr leafn)
01340 {
01341   /* Just make sure that the leaf is not already there */
01342   IGLptr p;
01343 
01344   if(r == NULL)
01345     return;
01346   p = r -> leaves;
01347   while(p != NULL){
01348     /*    xsb_warn("loopd"); */
01349     if(p -> leaf == leafn){
01350       /* The following should be permitted, because we should be able to
01351          backtrackably delete backtrackably deleted nodes (which should have no
01352          effect)
01353       */
01354       if (IsDeletedNode(leafn))
01355         xsb_dbgmsg((LOG_INTERN,
01356                    "The leaf node being deleted has already been deleted"));
01357       return;
01358     }
01359     p = p -> next;
01360   }
01361   p = newIGL(leafn);
01362   p -> next = r -> leaves;
01363   r -> leaves = p;
01364 }
01365 
01366 
01367 /*
01368  * This is builtin : TRIE_DISPOSE_NR(+ROOT, +LEAF), to
01369  * mark for  disposal a branch
01370  * of the trie rooted at Set_ArrayPtr[ROOT].
01371  */
01372 void trie_dispose_nr(CTXTdecl)
01373 {
01374   BTNptr Leaf;
01375   long Rootidx;
01376 
01377   Rootidx = ptoc_int(CTXTc 1);
01378   Leaf = (BTNptr)ptoc_int(CTXTc 2);
01379   switch_to_trie_assert;
01380   insertLeaf(getIGRnode(CTXTc Rootidx), Leaf);
01381   safe_delete_branch(Leaf);
01382   switch_from_trie_assert;
01383 }
01384 
01385 
01386 void reclaim_uninterned_nr(CTXTdeclc long rootidx)
01387 {
01388   IGRptr r = getAndRemoveIGRnode(CTXTc rootidx);
01389   IGLptr l, p;
01390   BTNptr leaf;
01391 
01392   if (r!=NULL)
01393     l = r-> leaves;
01394   else
01395     return;
01396 
01397   mem_dealloc(r,sizeof(InternGarbageRoot),TABLE_SPACE);
01398 
01399   while(l != NULL){
01400     /* printf("Loop b %p\n", l); */
01401     leaf = l -> leaf;
01402     p = l -> next;
01403     mem_dealloc(l,sizeof(InternGarbageLeaf),TABLE_SPACE);
01404     switch_to_trie_assert;
01405     if(IsDeletedNode(leaf)) {
01406       delete_branch(CTXTc leaf, &(Set_ArrayPtr[rootidx]));
01407     } else {
01408       /* This is allowed:
01409          If we backtrack over a delete, the node that was marked for deletion
01410          and placed in the garbage list is unmarked, but isn't removed from
01411          the garbage list. So it is a non-deleted node on the garbage list.
01412          It is removed from there only when we reclaim space.
01413       */
01414       xsb_dbgmsg((LOG_INTERN,"Non deleted interned node in garbage list - ok"));
01415     }
01416 
01417     switch_from_trie_assert;
01418     l = p;
01419   }
01420 
01421 }
01422 
01423 /*----------------------------------------------------------------------*/
01424 
01425 void trie_undispose(CTXTdeclc long rootIdx, BTNptr leafn)
01426 {
01427   IGRptr r = getIGRnode(CTXTc rootIdx);
01428   IGLptr p = r -> leaves;
01429   if(p == NULL){
01430     xsb_dbgmsg((LOG_INTERN,
01431    "In trie_undispose: The node being undisposed has been previously deleted"));
01432   } else{
01433     if(p -> leaf == leafn){
01434       r -> leaves = p -> next;
01435       mem_dealloc(p,sizeof(InternGarbageLeaf),TABLE_SPACE);
01436       if(r -> leaves == NULL){
01437         /* Do not want roots with no leaves hanging around */
01438         getAndRemoveIGRnode(CTXTc rootIdx);
01439       }
01440     }
01441     undelete_branch(leafn);
01442   }
01443 }
01444 
01445 /*----------------------------------------------------------------------*/
01446 
01447 /* TABLE ABOLISHING AND GARBAGE COLLECTING 
01448  *
01449  * When a table is abolished, various checks must be made before its
01450  * space can be reclaimed.  First, the table must be completed, and
01451  * second it must be ensured that there are not any trie choice points
01452  * for the table in the choice point stack.  Third, if the table is
01453  * shared, a check must be made that there is a single active thread.
01454  *
01455  * In the case of abolish_all_tables, if there are any incomplete
01456  * tables, or if there are trie nodes for completed tables on the
01457  * choice point stack, an error is thrown.  In the case of
01458  * abolish_table_pred(P) (and other abolishes), if P is not completed
01459  * an error is thrown; while if trie choice points for P are on the
01460  * stack, P is "abolished" (pointers in the TIF are reset) but its
01461  * space is not yet reclaimed.  Rather, a deleted table frame (DelTF)
01462  * is set up so that P can later be reclaimed upon a call to
01463  * gc_tables/1.  The same action is also taken if P is shared and
01464  * there is more than one active thread.  Note that if we have to
01465  * create a DelTF for them, even private tables will not be gc'd until
01466  * we're down to a single thread, so its best to call the abolishes
01467  * when we dont have any more backtracking points.
01468  *
01469  * Later, on a call to gc_tables/1 (which works only if there is a
01470  * single active thread), the choice point stacks may be traversed to
01471  * mark those DelTF frames corresponding to tables with trie CPs in
01472  * the CP stack.  Once this is done, the chain of DelTF frames is
01473  * traversed to reclaim tables for those unmarked DelTF frames (and
01474  * free the frames) as well as to unmark the marked DelTF frames.
01475  * 
01476  * Note that all of these require SLG_GC to be defined as we need to
01477  * properly traverse the CPS.  So, probably we should take out SLG_GC.
01478  */
01479 
01480 /*------------------------------------------------------------------*/
01481 /* Utility Code */
01482 /*------------------------------------------------------------------*/
01483 
01484 /* used by mt engine for shared tables */
01485 DelTFptr deltf_chain_begin = (DelTFptr) NULL;
01486 
01487 #define is_trie_instruction(cp_inst) \
01488  ((int) cp_inst >= 0x5c && (int) cp_inst < 0x80) \
01489            || ((int) cp_inst >= 0x90 && (int) cp_inst < 0x94) 
01490 
01491 /* - - - - - */
01492 
01493 xsbBool is_completed_table(TIFptr tif) {
01494   VariantSF sf;
01495 
01496   for ( sf = TIF_Subgoals(tif);  IsNonNULL(sf);  
01497         sf = (VariantSF)subg_next_subgoal(sf) )
01498     if ( ! is_completed(sf) )
01499       return FALSE;
01500   return TRUE;
01501 }
01502 
01503 /* - - - - - */
01504 
01505 Psc get_psc_for_answer_trie_cp(CTXTdeclc BTNptr pLeaf) 
01506 {
01507   TIFptr tif_ptr;
01508 
01509   while ( IsNonNULL(pLeaf) && (! IsTrieRoot(pLeaf)) && 
01510                                ((int) TN_Instr(pLeaf) != trie_fail_unlock) ) {
01511     pLeaf = BTN_Parent(pLeaf);
01512   }
01513 
01514   if (TN_Parent(pLeaf)) { /* workaround till all roots pointing to subg's */
01515     tif_ptr = subg_tif_ptr(TN_Parent(pLeaf));
01516     //    printf("Predicate is %s/%d\n",get_name(TIF_PSC(tif_ptr)),
01517     //    get_arity(TIF_PSC(tif_ptr)));
01518     return TIF_PSC(tif_ptr);
01519   } else {
01520     fprintf(stderr,"Null parent ptr for TN Root Node type: %d Trie type %d\n",
01521             TN_TrieType(pLeaf), TN_NodeType(pLeaf));
01522     return NULL;
01523   }
01524 }
01525 
01526 /* - - - - - */
01527 
01528 VariantSF get_subgoal_frame_for_answer_trie_cp(CTXTdeclc BTNptr pLeaf) 
01529 {
01530 
01531   while ( IsNonNULL(pLeaf) && (! IsTrieRoot(pLeaf)) && 
01532                                ((int) TN_Instr(pLeaf) != trie_fail_unlock) ) {
01533     pLeaf = BTN_Parent(pLeaf);
01534   }
01535 
01536   if (TN_Parent(pLeaf)) { /* workaround till all roots pointing to subg's */
01537     return (VariantSF) TN_Parent(pLeaf);
01538   } else {
01539     fprintf(stderr,"Null parent ptr for TN Root Node type: %d Trie type %d\n",
01540             TN_TrieType(pLeaf), TN_NodeType(pLeaf));
01541     return NULL;
01542   }
01543 }
01544 
01545 /* - - - - - */
01546 
01547 TIFptr get_tif_for_answer_trie_cp(CTXTdeclc BTNptr pLeaf)
01548 {
01549 
01550   while ( IsNonNULL(pLeaf) && (! IsTrieRoot(pLeaf)) && 
01551                                ((int) TN_Instr(pLeaf) != trie_fail_unlock) ) {
01552     pLeaf = BTN_Parent(pLeaf);
01553   }
01554   return subg_tif_ptr(TN_Parent(pLeaf));
01555 }
01556 
01557 /* - - - - - */
01558 
01559 /* If there is a deltf with same subgoals and arity (can this be) dont
01560    add; otherwise if there is a subgoal for this pred, delete the
01561    deltf (it must be for this generation of the table)
01562 */
01563 void check_insert_global_deltf_pred(CTXTdeclc TIFptr tif) { 
01564   DelTFptr dtf = TIF_DelTF(tif), next_dtf; 
01565   BTNptr call_trie = TIF_CallTrie(tif); 
01566   VariantSF subgoals = TIF_Subgoals(tif); 
01567   int found = 0;
01568 
01569   SYS_MUTEX_LOCK(MUTEX_TABLE);
01570   while ( dtf != 0 ) {
01571     next_dtf = DTF_NextPredDTF(dtf);
01572     if (DTF_Type(dtf) == DELETED_PREDICATE && 
01573         DTF_CallTrie(dtf) == call_trie && DTF_Subgoals(dtf) == subgoals)
01574       found = 1;
01575     if (DTF_Type(dtf) == DELETED_SUBGOAL) {
01576       //      fprintf(stderr,"Predicate over-riding subgoal for %s/%d\n",
01577       //      get_name(TIF_PSC(tif)),get_arity(TIF_PSC(tif)));
01578       Free_Global_DelTF_Subgoal(dtf,tif);
01579     }
01580     dtf = next_dtf;
01581   }
01582   if (!found) {
01583     New_Global_DelTF_Pred(dtf,tif);
01584   }
01585   TIF_CallTrie(tif) = NULL;
01586   TIF_Subgoals(tif) = NULL;
01587   SYS_MUTEX_UNLOCK(MUTEX_TABLE);
01588 }
01589 
01590 /* Dont think I need to check for deleted subgoals. */
01591 void check_insert_global_deltf_subgoal(CTXTdeclc VariantSF subgoal) {
01592   DelTFptr dtf;
01593   TIFptr tif;
01594 
01595   SYS_MUTEX_LOCK(MUTEX_TABLE);
01596 
01597   tif = subg_tif_ptr(subgoal);
01598 
01599   New_Global_DelTF_Subgoal(dtf,tif,subgoal);
01600 
01601   if (subg_prev_subgoal(subgoal) != 0) 
01602     subg_prev_subgoal(subgoal) = subg_next_subgoal(subgoal);
01603 
01604   if (subg_next_subgoal(subgoal) != 0) 
01605     subg_next_subgoal(subgoal) = subg_prev_subgoal(subgoal);
01606 
01607   subg_deltf_ptr(subgoal) = dtf;
01608 
01609   SYS_MUTEX_UNLOCK(MUTEX_TABLE);
01610 }
01611 
01612 #ifdef MULTI_THREAD
01613 
01614 void check_insert_private_deltf_pred(CTXTdeclc TIFptr tif) {
01615   DelTFptr dtf = TIF_DelTF(tif);
01616   BTNptr call_trie = TIF_CallTrie(tif);
01617   VariantSF subgoals = TIF_Subgoals(tif);       
01618   int found = 0;
01619 
01620   while ( dtf != 0 ) {
01621     if (DTF_Type(dtf) == DELETED_PREDICATE && 
01622         DTF_CallTrie(dtf) == call_trie && DTF_Subgoals(dtf) == subgoals)
01623       found = 1;
01624     if (DTF_Type(dtf) == DELETED_SUBGOAL) {
01625       //      fprintf(stderr,"Predicate over-riding subgoal for %s/%d\n",
01626       //      get_name(TIF_PSC(tif)),get_arity(TIF_PSC(tif)));
01627       Free_Private_DelTF_Subgoal(dtf,tif);
01628     }
01629     dtf = DTF_NextPredDTF(dtf);
01630   }
01631   if (!found) {
01632     New_Private_DelTF_Pred(dtf,tif);
01633   }
01634   TIF_CallTrie(tif) = NULL;
01635   TIF_Subgoals(tif) = NULL;
01636 }
01637 
01638 #define check_insert_shared_deltf_pred(context, tif)    \
01639   check_insert_global_deltf_pred(context, tif)   
01640 
01641 /* * * * * * * */
01642 
01643 void check_insert_private_deltf_subgoal(CTXTdeclc VariantSF subgoal)
01644 {
01645   DelTFptr dtf;
01646   TIFptr tif = subg_tif_ptr(subgoal);
01647 
01648   New_Private_DelTF_Subgoal(dtf,tif,subgoal);
01649 
01650   if (subg_prev_subgoal(subgoal) != 0) 
01651     subg_prev_subgoal(subgoal) = subg_next_subgoal(subgoal);
01652 
01653   if (subg_next_subgoal(subgoal) != 0) 
01654     subg_next_subgoal(subgoal) = subg_prev_subgoal(subgoal);
01655 
01656   subg_deltf_ptr(subgoal) = dtf;
01657 }
01658 
01659 #define check_insert_shared_deltf_subgoal(context, subgoal)     \
01660   check_insert_global_deltf_subgoal(context, subgoal)    
01661 
01662 #else /* not MULTI_THREAD */
01663 
01664 #define check_insert_private_deltf_pred(tif)    \
01665   check_insert_global_deltf_pred(tif)    
01666 
01667 #define check_insert_private_deltf_subgoal(subgoal)     \
01668   check_insert_global_deltf_subgoal(subgoal)     
01669 
01670 #endif
01671 
01672 /* - - - - - - - - - - */
01673 
01674 /* Assumes cps check has already been done, so that mark bit is set on
01675  * TIFs.  Assumes TIF is non-null.  Tif chain is not changed,
01676  * therefore no need for mutex.  Reclaims space for shared tables only
01677  * if 1 active thread.
01678  */  
01679 
01680 int fast_abolish_table_predicate(CTXTdeclc Psc psc)
01681 {
01682   TIFptr tif;
01683 
01684   gc_tabled_preds(CTXT);
01685 
01686   tif = get_tip(CTXTc psc);
01687 
01688   if (IsVariantPredicate(tif) && IsNULL(TIF_CallTrie(tif))) {
01689     return 1;
01690   }
01691 
01692   if ( ! is_completed_table(tif) ) {
01693       xsb_abort("[abolish_table_pred] Cannot abolish incomplete table"
01694                 " of predicate %s/%d\n", get_name(psc), get_arity(psc));
01695   }
01696 
01697   if (!TIF_Mark(tif) && (!get_shared(psc) || flags[NUM_THREADS] == 1)) {
01698 
01699 #ifdef MULTI_THREAD  
01700     SET_TRIE_ALLOCATION_TYPE_PSC(psc);  // set pvt/shared SMs
01701 #endif
01702 
01703     delete_predicate_table(CTXTc tif);
01704   }  else {
01705     //    fprintf(stderr,"Delaying abolish of table in use: %s/%d\n",
01706     //    get_name(psc),get_arity(psc));
01707 #ifndef MULTI_THREAD
01708     check_insert_private_deltf_pred(CTXTc tif);
01709 #else
01710     if (!get_shared(psc))
01711       check_insert_private_deltf_pred(CTXTc tif);
01712     else
01713       check_insert_shared_deltf_pred(CTXT,tif);
01714 #endif
01715   }
01716 return 1;
01717 }
01718 
01719 /* - - - - - - - - - - */
01720 
01721 void mark_cp_tables(CTXTdecl)
01722 {
01723   CPtr cp_top,cp_bot ;
01724   byte cp_inst;
01725   TIFptr tif;
01726   
01727   cp_bot = (CPtr)(tcpstack.high) - CP_SIZE;
01728 
01729   cp_top = breg ;                                
01730   while ( cp_top < cp_bot ) {
01731     cp_inst = *(byte *)*cp_top;
01732     // Want trie insts, but will need to distinguish from
01733     // asserted and interned tries
01734     if ( is_trie_instruction(cp_inst) ) {
01735       if (IsInAnswerTrie((BTNptr) *cp_top)) {
01736         tif = get_tif_for_answer_trie_cp(CTXTc (BTNptr) *cp_top);
01737         cps_check_mark_tif(tif);
01738       }
01739     }
01740     cp_top = cp_prevtop(cp_top);
01741   }
01742 }
01743 
01744 void unmark_cp_tables(CTXTdecl)
01745 {
01746   CPtr cp_top,cp_bot ;
01747   byte cp_inst;
01748   TIFptr tif;
01749   
01750   cp_bot = (CPtr)(tcpstack.high) - CP_SIZE;
01751 
01752   cp_top = breg ;                                
01753   while ( cp_top < cp_bot ) {
01754     cp_inst = *(byte *)*cp_top;
01755     // Want trie insts, but will need to distinguish from
01756     // asserted and interned tries
01757     if ( is_trie_instruction(cp_inst) ) {
01758       if (IsInAnswerTrie((BTNptr) *cp_top)) {
01759         tif = get_tif_for_answer_trie_cp(CTXTc (BTNptr) *cp_top);
01760         cps_check_unmark_tif(tif);
01761       }
01762     }
01763     cp_top = cp_prevtop(cp_top);
01764   }
01765 }
01766 
01767 /*------------------------------------------------------------------*/
01768 /* abolish_table_call() and supporting code */
01769 /*------------------------------------------------------------------*/
01770 
01771 /* 
01772    Recurse through CP stack looking for trie nodes that match PSC.
01773    Returns 1 if found a psc match, 0 if safe to delete now
01774 */
01775 
01776 int abolish_table_call_cps_check(CTXTdeclc VariantSF subgoal) 
01777 {
01778   CPtr cp_top,cp_bot ;
01779   byte cp_inst;
01780   int found_subgoal_match;
01781 
01782   cp_bot = (CPtr)(tcpstack.high) - CP_SIZE;
01783 
01784   cp_top = breg ;                                
01785   found_subgoal_match = 0;
01786   while ( cp_top < cp_bot && !(found_subgoal_match)) {
01787     cp_inst = *(byte *)*cp_top;
01788     // Want trie insts, but will need to distinguish from
01789     // asserted and interned tries
01790     if ( is_trie_instruction(cp_inst) ) {
01791       // Below we want basic_answer_trie_tt, ts_answer_trie_tt
01792       if (IsInAnswerTrie(((BTNptr) *cp_top))) {
01793         if (subgoal == 
01794             get_subgoal_frame_for_answer_trie_cp(CTXTc (BTNptr) *cp_top)) {
01795           found_subgoal_match = 1;
01796         }
01797       }
01798     }
01799     cp_top = cp_prevtop(cp_top);
01800   }
01801   return found_subgoal_match;
01802 }
01803 
01804 int abolish_table_call(CTXTdeclc VariantSF subgoal) {
01805 
01806     TIFptr tif;
01807     Psc psc;
01808     int action;
01809 
01810     subgoal = (VariantSF) ptoc_int(CTXTc 1);
01811     tif = subg_tif_ptr(subgoal);
01812     psc = TIF_PSC(tif);
01813 
01814     if (!is_completed(subgoal)) {
01815       xsb_abort("[abolish_table_call] Cannot abolish incomplete tabled call"
01816                 " of predicate %s/%d\n",get_name(psc),get_arity(psc));
01817     }
01818 
01819     if (flags[NUM_THREADS] == 1 || !get_shared(psc)) {
01820       action = abolish_table_call_cps_check(CTXTc subgoal);
01821     } else action = 1;
01822 
01823     if (!action) {
01824 #ifdef MULTI_THREAD      
01825       SET_TRIE_ALLOCATION_TYPE_SF(subgoal); // set smBTN to private/shared
01826 #endif
01827       delete_branch(CTXTc subgoal->leaf_ptr, &tif->call_trie); /* delete call */
01828       delete_variant_sf_and_answers(CTXTc subgoal); // delete answers
01829       return TRUE;
01830     }
01831     else {
01832       //      fprintf(stderr,"Delaying abolish of call in use for: %s/%d\n",
01833       //      get_name(psc),get_arity(psc));
01834 #ifndef MULTI_THREAD
01835       delete_branch(CTXTc subgoal->leaf_ptr, &tif->call_trie); /* delete call */
01836       check_insert_private_deltf_subgoal(CTXTc subgoal);
01837 #else
01838       if (!get_shared(psc)) {
01839         delete_branch(CTXTc subgoal->leaf_ptr, &tif->call_trie); /* delete call */
01840         check_insert_private_deltf_subgoal(CTXTc subgoal);
01841       }
01842       else {
01843         safe_delete_branch(subgoal->leaf_ptr); 
01844         check_insert_shared_deltf_subgoal(CTXT, subgoal);
01845       }
01846 #endif
01847       return TRUE;
01848     }
01849 }
01850 
01851 /*------------------------------------------------------------------*/
01852 /* abolish_table_pred() and supporting code */
01853 /*------------------------------------------------------------------*/
01854 
01855 /* 
01856    Recurse through CP stack looking for trie nodes that match PSC.
01857    Returns 1 if found a psc match, 0 if safe to delete now
01858 */
01859 
01860 int abolish_table_pred_cps_check(CTXTdeclc Psc psc) 
01861 {
01862   CPtr cp_top,cp_bot ;
01863   byte cp_inst;
01864   int found_psc_match;
01865 
01866   cp_bot = (CPtr)(tcpstack.high) - CP_SIZE;
01867 
01868   cp_top = breg ;                                
01869   found_psc_match = 0;
01870   while ( cp_top < cp_bot && !(found_psc_match)) {
01871     cp_inst = *(byte *)*cp_top;
01872     // Want trie insts, but will need to distinguish from
01873     // asserted and interned tries
01874     if ( is_trie_instruction(cp_inst) ) {
01875       // Below we want basic_answer_trie_tt, ts_answer_trie_tt
01876       if (IsInAnswerTrie(((BTNptr) *cp_top))) {
01877         if (psc == get_psc_for_answer_trie_cp(CTXTc (BTNptr) *cp_top)) {
01878           found_psc_match = 1;
01879         }
01880       }
01881     }
01882     cp_top = cp_prevtop(cp_top);
01883   }
01884   return found_psc_match;
01885 }
01886 
01887 /* Delays spece reclamation if the cps check does not pass OR if
01888    shared and more than 1 thread is active.
01889 
01890   abolish_table_predicate does not reclaim space for previously
01891  "abolished" tables in deltf frames.  Need to do gc tables for
01892   that. */
01893 
01894 inline int abolish_table_predicate(CTXTdeclc Psc psc)
01895 {
01896   TIFptr tif;
01897   int action;
01898 
01899   gc_tabled_preds(CTXT);
01900   tif = get_tip(CTXTc psc);
01901   if ( IsNULL(tif) ) {
01902     xsb_abort("[abolish_table_pred] Attempt to delete non-tabled predicate (%s/%d)\n",
01903               get_name(psc), get_arity(psc));
01904   }
01905   if (IsVariantPredicate(tif) && IsNULL(TIF_CallTrie(tif))) {
01906     return 1;
01907   }
01908 
01909   if ( ! is_completed_table(tif) ) {
01910       xsb_abort("[abolish_table_pred] Cannot abolish incomplete table"
01911                 " of predicate %s/%d\n", get_name(psc), get_arity(psc));
01912   }
01913 
01914   if (flags[NUM_THREADS] == 1 || !get_shared(psc)) {
01915     action = abolish_table_pred_cps_check(CTXTc psc);
01916   }
01917   else action = 1;
01918   if (!action) {
01919 
01920 #ifdef MULTI_THREAD  
01921     SET_TRIE_ALLOCATION_TYPE_PSC(psc);  // determine whether pvt/shared SMs
01922 #endif
01923 
01924     delete_predicate_table(CTXTc tif);
01925     return 1;
01926   }
01927   else {
01928     //    fprintf(stderr,"Delaying abolish of table in use: %s/%d\n",
01929     //    get_name(psc),get_arity(psc));
01930 #ifndef MULTI_THREAD
01931     check_insert_private_deltf_pred(CTXTc tif);
01932 #else
01933     if (!get_shared(psc))
01934       check_insert_private_deltf_pred(CTXTc tif);
01935     else
01936       check_insert_shared_deltf_pred(CTXT, tif);
01937 #endif
01938     return 1; 
01939   }
01940 }  
01941 
01942 /*------------------------------------------------------------------*/
01943 /* Table gc and supporting code */
01944 /*------------------------------------------------------------------*/
01945 
01946 /* Go through and mark DelTfs to ensure that on sweep we dont abolish
01947   "active" predicates we're backtracking through.  Note that only the
01948   first DelTF in the pred-specific chain may be active in this sense.
01949   And its active only if calltrie and subgoals for tif are 0 -- if
01950   they are 0, the table has been abolished (even though we're
01951   backtracking through it).  If they aren't 0, we're backtracking
01952   through a different table altogether, and we needn't mark.
01953 */
01954 
01955 void mark_tabled_preds(CTXTdecl) { 
01956   CPtr cp_top,cp_bot ; byte cp_inst;
01957   TIFptr tif;
01958   VariantSF subgoal;
01959   
01960   cp_bot = (CPtr)(tcpstack.high) - CP_SIZE;
01961 
01962   cp_top = breg ;                                
01963   while ( cp_top < cp_bot ) {
01964     cp_inst = *(byte *)*cp_top;
01965     // Want trie insts, but will need to distinguish from
01966     // asserted and interned tries
01967     if ( is_trie_instruction(cp_inst) ) {
01968       if (IsInAnswerTrie((BTNptr) *cp_top)) {
01969         DelTFptr dtf;
01970 
01971         /* Check for predicate DelTFs */
01972         tif = get_tif_for_answer_trie_cp(CTXTc (BTNptr) *cp_top);
01973         if (TIF_CallTrie(tif) == NULL && TIF_Subgoals(tif) == NULL) {
01974           dtf = TIF_DelTF(tif);
01975           DTF_Mark(dtf) = 1;
01976         }
01977         
01978         /* Now check for subgoal DelTFs */
01979         subgoal = get_subgoal_frame_for_answer_trie_cp(CTXTc (BTNptr) *cp_top);
01980         if (is_completed(subgoal)) {
01981           if (subg_deltf_ptr(subgoal) != NULL) {
01982             DTF_Mark((DelTFptr) subg_deltf_ptr(subgoal)) = 1;
01983           }
01984         }
01985       }
01986     }
01987     cp_top = cp_prevtop(cp_top);
01988   }
01989 }
01990 
01991 /* Mark only private tables -- ignore shared tables. Used by mt system
01992    when gc-ing with more than 1 active thread -- and used in lieu
01993    of mark_tabled_preds()
01994 */
01995 void mark_private_tabled_preds(CTXTdecl) { 
01996   CPtr cp_top,cp_bot ; byte cp_inst;
01997   TIFptr tif;
01998   VariantSF subgoal;
01999   
02000   cp_bot = (CPtr)(tcpstack.high) - CP_SIZE;
02001 
02002   cp_top = breg ;                                
02003   while ( cp_top < cp_bot ) {
02004     cp_inst = *(byte *)*cp_top;
02005     // Want trie insts, but will need to distinguish from
02006     // asserted and interned tries
02007     if ( is_trie_instruction(cp_inst) ) {
02008       if (IsInAnswerTrie((BTNptr) *cp_top)) {
02009         DelTFptr dtf;
02010 
02011         /* Check for predicate DelTFs */
02012         tif = get_tif_for_answer_trie_cp(CTXTc (BTNptr) *cp_top);
02013         if (TIF_CallTrie(tif) == NULL && TIF_Subgoals(tif) == NULL 
02014             && !get_shared(TIF_PSC(tif))) { 
02015           dtf = TIF_DelTF(tif);
02016           DTF_Mark(dtf) = 1;
02017         }
02018 
02019         /* Now check for subgoal DelTFs */
02020         subgoal = get_subgoal_frame_for_answer_trie_cp(CTXTc (BTNptr) *cp_top);
02021         if (is_completed(subgoal) 
02022             && !get_shared(TIF_PSC(subg_tif_ptr(subgoal)))) {
02023           if (subg_deltf_ptr(subgoal) != NULL) {
02024             DTF_Mark((DelTFptr) subg_deltf_ptr(subgoal)) = 1;
02025           }
02026         }
02027       }
02028     }
02029     cp_top = cp_prevtop(cp_top);
02030   }
02031 }
02032 
02033 #ifdef MULTI_THREAD
02034 int sweep_private_tabled_preds(CTXTdecl) {
02035   DelTFptr deltf_ptr, next_deltf_ptr;
02036   int dtf_cnt = 0;
02037   TIFptr tif_ptr;
02038 
02039   deltf_ptr = private_deltf_chain_begin;
02040   while (deltf_ptr) {
02041     next_deltf_ptr = DTF_NextDTF(deltf_ptr);
02042     if (DTF_Mark(deltf_ptr)) {
02043       tif_ptr = subg_tif_ptr(DTF_Subgoals(deltf_ptr));
02044       //      fprintf(stderr,"Skipping: %s/%d\n",
02045       //      get_name(TIF_PSC(tif_ptr)),get_arity(TIF_PSC(tif_ptr)));
02046       DTF_Mark(deltf_ptr) = 0;
02047       dtf_cnt++;
02048     }
02049     else {
02050       if (DTF_Type(deltf_ptr) == DELETED_PREDICATE) {
02051         tif_ptr = subg_tif_ptr(DTF_Subgoals(deltf_ptr));
02052         //      fprintf(stderr,"Garbage Collecting Predicate: %s/%d\n",
02053         // get_name(TIF_PSC(tif_ptr)),get_arity(TIF_PSC(tif_ptr)));
02054         reclaim_deleted_predicate_table(CTXTc deltf_ptr);
02055         Free_Private_DelTF_Pred(deltf_ptr,tif_ptr);
02056       } else 
02057         if (DTF_Type(deltf_ptr) == DELETED_SUBGOAL) {
02058           tif_ptr = subg_tif_ptr(DTF_Subgoal(deltf_ptr));
02059           //      fprintf(stderr,"Garbage Collecting Subgoal: %s/%d\n",
02060           //  get_name(TIF_PSC(tif_ptr)),get_arity(TIF_PSC(tif_ptr)));
02061           delete_variant_sf_and_answers(CTXTc DTF_Subgoal(deltf_ptr)); 
02062           Free_Private_DelTF_Subgoal(deltf_ptr,tif_ptr);
02063         }
02064     }
02065     deltf_ptr = next_deltf_ptr;
02066   }
02067   return dtf_cnt;
02068 }
02069 #endif
02070 
02071 /* No mutex on this predicate, as global portions can only be called
02072    with one active thread */
02073 
02074 int sweep_tabled_preds(CTXTdecl) {
02075   DelTFptr deltf_ptr, next_deltf_ptr;
02076   int dtf_cnt = 0;
02077   TIFptr tif_ptr;
02078 
02079   /* Free global deltfs */
02080   deltf_ptr = deltf_chain_begin;
02081   while (deltf_ptr) {
02082     next_deltf_ptr = DTF_NextDTF(deltf_ptr);
02083     if (DTF_Mark(deltf_ptr)) {
02084       tif_ptr = subg_tif_ptr(DTF_Subgoals(deltf_ptr));
02085       //      fprintf(stderr,"Skipping: %s/%d\n",
02086       //      get_name(TIF_PSC(tif_ptr)),get_arity(TIF_PSC(tif_ptr)));
02087       DTF_Mark(deltf_ptr) = 0;
02088       dtf_cnt++;
02089     }
02090     else {
02091       if (DTF_Type(deltf_ptr) == DELETED_PREDICATE) {
02092         tif_ptr = subg_tif_ptr(DTF_Subgoals(deltf_ptr));
02093         //      fprintf(stderr,"Garbage Collecting Predicate: %s/%d\n",
02094         //get_name(TIF_PSC(tif_ptr)),get_arity(TIF_PSC(tif_ptr)));
02095         reclaim_deleted_predicate_table(CTXTc deltf_ptr);
02096         Free_Global_DelTF_Pred(deltf_ptr,tif_ptr);
02097       } else 
02098         if (DTF_Type(deltf_ptr) == DELETED_SUBGOAL) {
02099           tif_ptr = subg_tif_ptr(DTF_Subgoal(deltf_ptr));
02100           //      fprintf(stderr,"Garbage Collecting Subgoal: %s/%d\n",
02101           //  get_name(TIF_PSC(tif_ptr)),get_arity(TIF_PSC(tif_ptr)));
02102           delete_variant_sf_and_answers(CTXTc DTF_Subgoal(deltf_ptr)); 
02103           Free_Global_DelTF_Subgoal(deltf_ptr,tif_ptr);
02104         }
02105     }
02106     deltf_ptr = next_deltf_ptr;
02107   }
02108 
02109 #ifdef MULTI_THREAD
02110   dtf_cnt = dtf_cnt + sweep_private_tabled_preds(CTXT);
02111 #endif
02112 
02113   return dtf_cnt;
02114 }
02115 
02116 /* * * * * * * * * * * * * * * 
02117  * In MT engine gcs does not gc shared tables if there is more than
02118  * one thread. 
02119  */
02120 
02121 #ifndef MULTI_THREAD
02122 int gc_tabled_preds(CTXTdecl) 
02123 {
02124     mark_tabled_preds(CTXT);
02125     return sweep_tabled_preds(CTXT);
02126   return 0;
02127 }
02128 #else
02129 int gc_tabled_preds(CTXTdecl) 
02130 {
02131 
02132   if (flags[NUM_THREADS] == 1) {
02133     mark_tabled_preds(CTXT);
02134     return sweep_tabled_preds(CTXT);
02135   } else {
02136     mark_private_tabled_preds(CTXT);
02137     return sweep_private_tabled_preds(CTXT);
02138   } 
02139 }
02140 #endif
02141 
02142 /*----------------------------------------------------------------------*/
02143 /* abolish_module_tables() and supporting code */
02144 /*------------------------------------------------------------------*/
02145 
02146 /* - - - - - - - - - - */
02147 
02148 int abolish_usermod_tables(CTXTdecl)
02149 {
02150   unsigned long i;
02151   Pair pair;
02152   Psc psc;
02153 
02154   mark_cp_tables(CTXT);
02155 
02156   for (i=0; i<symbol_table.size; i++) {
02157     if ((pair = (Pair) *(symbol_table.table + i))) {
02158       byte type;
02159       
02160       psc = pair_psc(pair);
02161       type = get_type(psc);
02162       if (type == T_DYNA || type == T_PRED) 
02163         if (!get_data(psc) ||
02164             !strcmp(get_name(get_data(psc)),"usermod") ||
02165             !strcmp(get_name(get_data(psc)),"global")) 
02166           if (get_tabled(psc)) {
02167             fast_abolish_table_predicate(CTXTc psc);
02168           }
02169     }
02170   }
02171 
02172   unmark_cp_tables(CTXT);
02173 
02174   return TRUE;
02175 }
02176 
02177 /* - - - - - - - - - - */
02178 
02179 int abolish_module_tables(CTXTdeclc const char *module_name)
02180 {
02181   Pair modpair, pair;
02182   byte type;
02183   Psc psc, module;
02184   
02185   mark_cp_tables(CTXT);
02186   modpair = (Pair) flags[MOD_LIST];
02187   
02188   while (modpair && 
02189          strcmp(module_name,get_name(pair_psc(modpair))))
02190     modpair = pair_next(modpair);
02191 
02192   if (!modpair) {
02193     xsb_warn("[abolish_module_tables] Module %s not found.\n",
02194                 module_name);
02195     return FALSE;
02196   }
02197 
02198   module = pair_psc(modpair);
02199   pair = (Pair) get_data(module);
02200 
02201   while (pair) {
02202     psc = pair_psc(pair);
02203     type = get_type(psc);
02204     if (type == T_DYNA || type == T_PRED) 
02205       if (get_tabled(psc)) {
02206         fast_abolish_table_predicate(CTXTc psc);
02207       }
02208     pair = pair_next(pair);
02209   }
02210   unmark_cp_tables(CTXT);
02211   return TRUE;
02212 }
02213 
02214 /*----------------------------------------------------------------------*/
02215 /* abolish_private/shared_tables() and supporting code */
02216 /*------------------------------------------------------------------*/
02217 
02218 #ifdef MULTI_THREAD
02219 
02220 /* will not reclaim space if more than one thread (via fast_atp) */
02221 void abolish_shared_tables(CTXTdecl) {
02222   TIFptr abol_tif;
02223 
02224   mark_cp_tables(CTXT);
02225 
02226   SYS_MUTEX_LOCK( MUTEX_TABLE );                                
02227   for (abol_tif = tif_list.first ; abol_tif != NULL
02228          ; abol_tif = TIF_NextTIF(abol_tif) ) {
02229       fast_abolish_table_predicate(CTXTc TIF_PSC(abol_tif));
02230   }
02231   SYS_MUTEX_UNLOCK( MUTEX_TABLE );                              
02232 
02233   unmark_cp_tables(CTXT);
02234 
02235 }
02236 
02237 void abolish_private_tables(CTXTdecl) {
02238   TIFptr abol_tif;
02239 
02240   mark_cp_tables(CTXT);
02241 
02242   for (abol_tif = private_tif_list.first ; abol_tif != NULL
02243          ; abol_tif = TIF_NextTIF(abol_tif) ) {
02244       fast_abolish_table_predicate(CTXTc TIF_PSC(abol_tif));
02245   }
02246 
02247   unmark_cp_tables(CTXT);
02248 
02249 }
02250 
02251 extern struct TDispBlkHdr_t tdispblkhdr; // defined in loader
02252 
02253 /* TLS: mutex may not be needed here, as we're freeing private
02254    resources.  This function handles the case when one thread creates
02255    a private tif, exits, its xsb_thread_id is reused, and the new
02256    thread creates a private tif for the same table.  */
02257 
02258 void thread_free_private_tifs(CTXTdecl) {
02259   struct TDispBlk_t *tdispblk;
02260   TIFptr tip;
02261 
02262   SYS_MUTEX_LOCK( MUTEX_TABLE );
02263   for (tdispblk=tdispblkhdr.firstDB 
02264          ; tdispblk != NULL ; tdispblk=tdispblk->NextDB) {
02265     if (th->tid <= tdispblk->MaxThread) {
02266       tip = (&(tdispblk->Thread0))[th->tid];
02267       if (tip) {
02268         (&(tdispblk->Thread0))[th->tid] = (TIFptr) NULL;
02269         Free_Private_TIF(tip);
02270       }
02271     }
02272   }
02273   SYS_MUTEX_UNLOCK( MUTEX_TABLE );
02274 }
02275 
02276 static inline void thread_free_private_deltfs(CTXTdecl) {
02277 
02278   DelTFptr next_deltf;
02279   DelTFptr deltf = private_deltf_chain_begin;
02280 
02281   while (deltf) {
02282     next_deltf = DTF_NextDTF(deltf);
02283     mem_dealloc(deltf,sizeof(DeletedTableFrame),TABLE_SPACE);           
02284     deltf = next_deltf;
02285   }
02286 }
02287 
02288 void release_private_tabling_resources(CTXTdecl) {
02289 
02290   thread_free_private_deltfs(CTXT);
02291   thread_free_private_tifs(CTXT);
02292   SM_ReleaseResources(*private_smTableBTN);
02293   TrieHT_FreeAllocatedBuckets(*private_smTableBTHT);
02294   SM_ReleaseResources(*private_smTableBTHT);
02295   SM_ReleaseResources(*private_smTSTN);
02296   TrieHT_FreeAllocatedBuckets(*private_smTSTHT);
02297   SM_ReleaseResources(*private_smTSTHT);
02298   SM_ReleaseResources(*private_smTSIN);
02299   SM_ReleaseResources(*private_smALN);
02300   SM_ReleaseResources(*private_smVarSF);
02301   SM_ReleaseResources(*private_smProdSF);
02302   SM_ReleaseResources(*private_smConsSF);
02303 }
02304 
02305 #endif
02306 
02307 /*----------------------------------------------------------------------*/
02308 /* abolish_all_tables() and supporting code */
02309 /*------------------------------------------------------------------*/
02310 
02311 /*
02312  * Frees all the tabling space resources (with a hammer)
02313  */
02314 
02315 void release_all_tabling_resources(CTXTdecl) {
02316   SM_ReleaseResources(smTableBTN);
02317   TrieHT_FreeAllocatedBuckets(smTableBTHT);
02318   SM_ReleaseResources(smTableBTHT);
02319   SM_ReleaseResources(smTSTN);
02320   TrieHT_FreeAllocatedBuckets(smTSTHT);
02321   SM_ReleaseResources(smTSTHT);
02322   SM_ReleaseResources(smTSIN);
02323   SM_ReleaseResources(smALN);
02324   SM_ReleaseResources(smVarSF);
02325   SM_ReleaseResources(smProdSF);
02326   SM_ReleaseResources(smConsSF);
02327 }
02328 
02329 /* TLS: Unlike the other abolishes, "all" aborts if it detects the
02330    presence of CPs for completed tables (incomplete tables are caught
02331    as before, by examining the completion stack).  It also aborts if
02332    called with more than one thread.
02333 */
02334 
02335 void abolish_all_tables_cps_check(CTXTdecl) 
02336 {
02337   CPtr cp_top,cp_bot ;
02338   byte cp_inst;
02339   int trie_type;
02340 
02341   cp_bot = (CPtr)(tcpstack.high) - CP_SIZE;
02342 
02343   cp_top = breg ;                                
02344   while ( cp_top < cp_bot ) {
02345     cp_inst = *(byte *)*cp_top;
02346     /* Check for trie instructions */
02347     if ( is_trie_instruction(cp_inst)) {
02348       trie_type = (int) TN_TrieType((BTNptr) *cp_top);
02349       /* Here, we want call_trie_tt,basic_answer_trie_tt,
02350          ts_answer_trie_tt","delay_trie_tt */
02351       if (IsInAnswerTrie(((BTNptr) *cp_top))) {
02352         xsb_abort("[abolish_all_tables/0] Illegal table operation"
02353                   "\n\t Backtracking through tables to be abolished.");
02354       }
02355     }
02356       cp_top = cp_prevtop(cp_top);
02357   }
02358 }
02359 
02360 #if !defined(WIN_NT) || defined(CYGWIN) 
02361 inline 
02362 #endif
02363 void abolish_table_info(CTXTdecl)
02364 {
02365   CPtr csf;
02366   TIFptr pTIF;
02367 
02368   for ( csf = top_of_complstk;  csf != COMPLSTACKBOTTOM;
02369         csf = csf + COMPLFRAMESIZE )
02370     if ( ! is_completed(compl_subgoal_ptr(csf)) ) {
02371       xsb_table_error(CTXTc "[abolish_all_tables/0] Illegal table operation"
02372                 "\n\t Cannot abolish incomplete tables");
02373     }
02374 
02375   if (flags[NUM_THREADS] == 1) {
02376     abolish_all_tables_cps_check(CTXT) ;
02377   } else {
02378     xsb_table_error(CTXTc 
02379                     "abolish_all_tables/1 called with more than one active thread.");
02380   }
02381    
02382   for ( pTIF = tif_list.first; IsNonNULL(pTIF); pTIF = TIF_NextTIF(pTIF) ) {
02383     TIF_CallTrie(pTIF) = NULL;
02384     TIF_Subgoals(pTIF) = NULL;
02385   }
02386 
02387 #ifdef MULTI_THREAD
02388   for ( pTIF = private_tif_list.first; IsNonNULL(pTIF)
02389           ; pTIF = TIF_NextTIF(pTIF) ) {
02390     TIF_CallTrie(pTIF) = NULL;
02391     TIF_Subgoals(pTIF) = NULL;
02392   }
02393 #endif
02394 
02395   reset_freeze_registers;
02396   openreg = COMPLSTACKBOTTOM;
02397   release_all_tabling_resources(CTXT);
02398   abolish_wfs_space(CTXT); 
02399 }
02400 
02401 /*
02402 * void abolish_if_tabled(CTXTdeclc Psc psc)
02403 * {
02404 *   CPtr ep;
02405 * 
02406 *   ep = (CPtr) get_ep(psc);
02407 *   switch (*(pb)ep) {
02408 *   case tabletry:
02409 *   case tabletrysingle:
02410 *     abolish_table_predicate(CTXTc psc);
02411 *     break;
02412 *   case test_heap:
02413 *     if (*(pb)(ep+2) == tabletry || *(pb)(ep+2) == tabletrysingle)
02414 *       abolish_table_predicate(CTXTc psc);
02415 *     break;
02416 *   case switchon3bound:
02417 *   case switchonbound:
02418 *   case switchonterm:
02419 *     if (*(pb)(ep+3) == tabletry || *(pb)(ep+3) == tabletrysingle)
02420 *       abolish_table_predicate(CTXTc psc);
02421 *     break;
02422 *   }
02423 * }
02424 */
02425 

Generated on Wed Jul 26 13:30:43 2006 for XSB by  doxygen 1.4.5