complete_local.h

00001 /* File:      complete_local.h
00002 ** Author(s): Juliana Freire, Kostis Sagonas, Terry Swift, Luis Castro
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-2001
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: complete_local.h,v 1.13 2005/11/17 23:24:24 tswift Exp $
00022 ** 
00023 */
00024 #ifndef __COMPLETE_LOCAL_H__
00025 #define __COMPLETE_LOCAL_H__
00026 
00027 #ifdef LOCAL_EVAL
00028 void makeConsumerFromGenerator(CTXTdeclc VariantSF producer_sf)
00029 {
00030   xsb_dbgmsg((LOG_COMPLETION,
00031               "Transforming %x from a generator to consumer (prev %x)\n",
00032               breg,nlcp_prevbreg(breg)));
00033   nlcp_trie_return(breg) = subg_ans_list_ptr(producer_sf);
00034   nlcp_pcreg(breg) = (pb) &answer_return_inst;
00035   nlcp_prevlookup(breg) = subg_asf_list_ptr(producer_sf);
00036 #ifdef CONC_COMPL
00037   nlcp_tid(breg) = makeint(th->tid);
00038 #endif
00039   subg_asf_list_ptr(producer_sf) = breg;
00040 }
00041 #endif /* LOCAL */
00042 
00043 #ifdef PROFILE
00044 #define ProfileLeader \
00045   { \
00046     int num_subgoals = 0; \
00047     int num_completed = 0; \
00048     int num_consumers_in_ascc = 0; \
00049     int num_compl_susps_in_ascc = 0; \
00050     int leader_level; \
00051     CPtr profile_CSF = cs_ptr; \
00052     VariantSF prof_compl_subg; \
00053 \
00054     leader_level = compl_level(profile_CSF); \
00055 \
00056     /* check from leader up to the youngest subgoal */ \
00057     while (profile_CSF >= openreg) { \
00058       num_subgoals++; \
00059       prof_compl_subg = compl_subgoal_ptr(profile_CSF); \
00060       if (is_completed(prof_compl_subg)) { /* this was early completed */ \
00061         num_completed++; \
00062       } \
00063       else { \
00064         CPtr nsf; \
00065         nsf = subg_asf_list_ptr(prof_compl_subg); \
00066         while (nsf != NULL) { \
00067           num_consumers_in_ascc++; \
00068           nsf = nlcp_prevlookup(nsf); \
00069           } \
00070         nsf = subg_compl_susp_ptr(prof_compl_subg); \
00071         while (nsf != NULL) { \
00072           num_compl_susps_in_ascc++; \
00073           nsf = csf_prevcsf(nsf); \
00074           } \
00075       } \
00076       profile_CSF = next_compl_frame(profile_CSF); \
00077     } \
00078     if (num_subgoals > max_subgoals) { max_subgoals = num_subgoals; } \
00079     if (num_completed > max_completed) { max_completed = num_completed; } \
00080     if (num_consumers_in_ascc > max_consumers_in_ascc) { \
00081       max_consumers_in_ascc = num_consumers_in_ascc; \
00082     } \
00083     if (num_compl_susps_in_ascc > max_compl_susps_in_ascc) { \
00084       max_compl_susps_in_ascc = num_compl_susps_in_ascc; \
00085     } \
00086     if (pflags[PROFFLAG] > 2) { \
00087       fprintf(stdmsg, \
00088               "p(lev(%d),lead(%d),subg(%d),ec(%d),cons(%d),cs(%d)).\n", \
00089               level_num,leader_level,num_subgoals,num_completed, \
00090              num_consumers_in_ascc,num_compl_susps_in_ascc); \
00091     } \
00092   }
00093 #else
00094 #define ProfileLeader
00095 #endif
00096 
00097 
00098 
00099 /* The following function writes the SDG to stddbg.  The SDG is
00100 written every "std_sample_rate" times the computation determines that
00101 it is checking completion for a leader.  If so, the opentable stack is
00102 traversed along with the various lists hanging off of the subgoal
00103 frames.  For each edge in the SDG a Prolog-readible fact is written
00104 
00105 edge(sdg_check_num,Type,Root_subgoal,Selected_tabled_subgoal)
00106 
00107 sdg_check_num is the number of the check.  Using sdg_check_num one can
00108 get a somewhat dynamic view of how the SDG changes over the
00109 computation.
00110 
00111 Type = 1 if it is a positive link (consumer choice point)
00112 Type = -1 if it is a negative link to a completion suspension choice point
00113 Type = 2 if it is the first call (generator cp is used here).  
00114 
00115 Right now, there isnt a good way of determining whether the first call
00116 of a tabled predicate is positive or negative.  So its best to table
00117 tnot/1 in tables.P if you want to keep full track of signs */
00118 
00119 #ifdef PROFILE
00120 void print_sdg_edge(int check_num,int sign,VariantSF fromsf,VariantSF tosf)
00121 {
00122   fprintf(stddbg,"edge(%d,%d,",check_num,sign);   
00123   print_subgoal(stddbg,fromsf); fprintf(stddbg,",");
00124   print_subgoal(stddbg,tosf); fprintf(stddbg,").\n");
00125 }
00126 
00127 void SpitOutGraph(CPtr cs_ptr)
00128 { 
00129   CPtr tmp_openreg = cs_ptr;
00130   CPtr nsf;
00131   int num_subgoals = 0; 
00132   VariantSF prof_compl_subg; 
00133   
00134   sdg_check_num++; 
00135   if (sdg_sample_rate > 0 && (sdg_check_num % sdg_sample_rate == 0)) { 
00136     printf(" /* now checking: %d */ \n",sdg_check_num);
00137     while (tmp_openreg < COMPLSTACKBOTTOM) {
00138       num_subgoals++;
00139       prof_compl_subg = compl_subgoal_ptr(tmp_openreg);
00140 
00141       fprintf(stddbg,"   /* ");
00142       print_subgoal(stddbg, prof_compl_subg); 
00143       fprintf(stddbg," */ \n");
00144 
00145       if (tcp_ptcp(subg_cp_ptr(prof_compl_subg)) != NULL ) {
00146       print_sdg_edge(sdg_check_num,2,
00147                      tcp_ptcp(subg_cp_ptr(prof_compl_subg)),
00148                      prof_compl_subg);
00149       } else {
00150       }
00151 
00152       nsf = subg_asf_list_ptr(prof_compl_subg); 
00153       while (nsf != NULL) {
00154 
00155         print_sdg_edge(sdg_check_num,1,nlcp_ptcp(nsf),prof_compl_subg);
00156 
00157         nsf = nlcp_prevlookup(nsf); 
00158       }
00159 
00160       nsf = subg_compl_susp_ptr(prof_compl_subg); 
00161       while (nsf != NULL) {
00162 
00163         print_sdg_edge(sdg_check_num,-1,csf_ptcp(nsf),prof_compl_subg);
00164 
00165         nsf = csf_prevcsf(nsf); 
00166       }
00167 
00168       tmp_openreg = prev_compl_frame(tmp_openreg);
00169     }
00170     /*    printf("doing checking %d %d \n",sdg_check_num,num_subgoals); */
00171   } 
00172 }
00173 #else
00174 #define SpitOutGraph
00175 #endif
00176 
00177 #ifdef LOCAL_EVAL
00178 #define DisposeOfComplSusp(subgoal) \
00179         subg_compl_susp_ptr(subgoal) = NULL
00180 #define DeleteCSF(nsf) \
00181         csf_prevcsf(nsf)
00182 
00183 /* TLS: A pass has been made through the CSF chain to remove those
00184  * whose root subgoal was early completed.  So what we do now is to
00185  * reset the hreg and breg of each.  Frankly I don't think that this
00186  * step should be needed if the freeze registers are not unset until
00187  * final completion, and the test suite passes if the alternate form
00188  * (below) is used.  I'll wait until the MT engine stabilizes until I
00189  * make the change, though.
00190  * 
00191  * 8/05 Took out lines     
00192  * cs_pcreg(nsftmp) = (pb) &resume_compl_suspension_inst;  
00193  * as these should be unnecessary, and appears to be an artifact from old code
00194  */
00195 #define ResumeCSFs() \
00196 { \
00197   CPtr nsftmp; \
00198   if (!cur_breg) { \
00199     cur_breg = cc_tbreg = nsf; \
00200   } else { \
00201     csf_prevcsf(cur_breg) = nsf; \
00202     cur_breg = nsf; \
00203   } \
00204   for (nsftmp = cur_breg; csf_prevcsf(nsftmp); nsftmp = csf_prevcsf(nsftmp)) {\
00205     cs_hreg(nsftmp) = hreg; \
00206     cs_ebreg(nsftmp) = ebreg; \
00207   } \
00208   cs_hreg(nsftmp) = hreg; \
00209   cs_ebreg(nsftmp) = ebreg; \
00210   csf_prevcsf(nsftmp) = breg; \
00211   cur_breg = nsftmp; \
00212   subg_compl_susp_ptr(compl_subg) = NULL; \
00213 }
00214 
00215 /* TLS: alternate form, that does not need to reset the hreg/ebreg.
00216 define ResumeCSFs()                             \
00217 { \
00218   CPtr nsftmp; \
00219   if (!cur_breg) { \
00220     cur_breg = cc_tbreg = nsf; \
00221   } else { \
00222     csf_prevcsf(cur_breg) = nsf; \
00223     cur_breg = nsf; \
00224   } \
00225   for (nsftmp = cur_breg; csf_prevcsf(nsftmp); nsftmp = csf_prevcsf(nsftmp)) {\
00226   } \
00227   csf_prevcsf(nsftmp) = breg; \
00228   cur_breg = nsftmp; \
00229   subg_compl_susp_ptr(compl_subg) = NULL; \
00230 }
00231 */
00232   
00233 static inline CPtr ProcessSuspensionFrames(CTXTdeclc CPtr cc_tbreg_in, 
00234                                            CPtr cs_ptr)
00235 {
00236   CPtr ComplStkFrame = cs_ptr;
00237   VariantSF compl_subg;
00238   CPtr cc_tbreg = cc_tbreg_in;
00239   CPtr cur_breg = NULL; /* tail of chain of nsf's; used in ResumeCSFs */
00240 
00241   /* check from leader up to the youngest subgoal */
00242   while (ComplStkFrame >= openreg) {
00243     compl_subg = compl_subgoal_ptr(ComplStkFrame);
00244     /* TLS: Explanation for the dull-witted (i.e. me).  If compl_subg
00245      * is early completed, this means it has an unconditional answer.
00246      * Since a completion suspension is set up only for ground
00247      * negative calls, this means that the compl suspension will fail,
00248      * so we just dispose of it.  BTW, this could also be done at
00249      * early completion (ans-return), though there's no big advantage
00250      * either way.
00251      */
00252     if (is_completed(compl_subg)) { /* this was early completed */
00253       DisposeOfComplSusp(compl_subg); /* set SGF pointer to null */
00254     }
00255     else { /* if not early completed */
00256       CPtr nsf;
00257       if ((nsf = subg_compl_susp_ptr(compl_subg)) != NULL) { 
00258         CPtr p, prev_nsf = NULL;
00259         /* check each suspension frame for appropriate action: if
00260          * their root subgoals are completed these completion
00261          * suspensions are irrelevant, so skip over them; o/w keep
00262          * them on chain, delay them, and let simplification take care
00263          * of the rest 
00264         */
00265         while (nsf) {
00266           if ((p = csf_ptcp(nsf)) != NULL) {
00267             if (is_completed(p)) {
00268               if (!prev_nsf) { /* deleting the first susp is special */
00269                 nsf = subg_compl_susp_ptr(compl_subg) = DeleteCSF(nsf);
00270               }
00271               else {
00272                 nsf = csf_prevcsf(prev_nsf) = DeleteCSF(nsf);
00273               }
00274             }
00275             else { /* this completion suspension will be delayed */
00276               mark_delayed(ComplStkFrame, subg_compl_stack_ptr(p), nsf);
00277               prev_nsf = nsf;
00278               nsf = csf_prevcsf(nsf);
00279             }
00280           }
00281         } /* while */
00282 
00283         if ((nsf = subg_compl_susp_ptr(compl_subg))) {
00284           ResumeCSFs();
00285         }
00286       } /* if there are completion suspensions */
00287     } /* else if not early completed */
00288     ComplStkFrame = next_compl_frame(ComplStkFrame);
00289   } /* while - for each subg in compl stack */
00290   return cc_tbreg;
00291 }
00292 
00293 static inline void CompleteSimplifyAndReclaim(CTXTdeclc CPtr cs_ptr)
00294 {
00295   VariantSF compl_subg;
00296   CPtr ComplStkFrame = cs_ptr; 
00297 
00298   /* mark all SCC as completed and do simplification also, reclaim
00299      space for all but the leader */
00300 
00301   while (ComplStkFrame >= openreg) {
00302     compl_subg = compl_subgoal_ptr(ComplStkFrame);
00303     mark_as_completed(compl_subg); 
00304     if (neg_simplif_possible(compl_subg)) {
00305       SYS_MUTEX_LOCK( MUTEX_DELAY ) ;
00306       simplify_neg_fails(CTXTc compl_subg);
00307       SYS_MUTEX_UNLOCK( MUTEX_DELAY ) ;
00308     }
00309 
00310     ComplStkFrame = next_compl_frame(ComplStkFrame);
00311   } /* while */
00312   
00313   /* TLS: placemarker while I develop it.  This function should happen
00314    *after* simplification and *before* removal of answer lists, which
00315    is useful for traversing dependency graphs. */
00316 
00317   /*  remove_unfounded_set(cs_ptr); */
00318       
00319   /* reclaim all answer lists, but the one for the leader */
00320   ComplStkFrame = next_compl_frame(cs_ptr);
00321   while (ComplStkFrame >= openreg) {
00322     compl_subg = compl_subgoal_ptr(ComplStkFrame);
00323     reclaim_incomplete_table_structs(compl_subg);
00324     ComplStkFrame = next_compl_frame(ComplStkFrame);
00325   } /* while */
00326 }
00327 
00328 static inline void SetupReturnFromLeader(CTXTdeclc CPtr orig_breg, CPtr cs_ptr, 
00329                                          VariantSF subgoal)
00330 {
00331   CPtr answer_template;
00332   int template_size, attv_num;
00333   Integer tmp;
00334 
00335   switch_envs(orig_breg); 
00336   /* check where this brings the stacks, that will determine how
00337      much can be reclaimed if there are answers to be returned */
00338   ptcpreg = tcp_ptcp(orig_breg);
00339   delayreg = tcp_pdreg(orig_breg);
00340   restore_some_wamregs(orig_breg, ereg);
00341   /* restore_trail_condition_registers - because success path
00342    * will be followed
00343    */
00344   ebreg = cp_ebreg(tcp_prevbreg(orig_breg));
00345   hbreg = cp_hreg(tcp_prevbreg(orig_breg));
00346   subg_asf_list_ptr(subgoal) = 0;
00347   
00348   /* reclaim stacks, including leader */
00349   openreg = prev_compl_frame(cs_ptr);
00350   reclaim_stacks(orig_breg);
00351   answer_template = tcp_template(breg);
00352   tmp = int_val(cell(answer_template));
00353   get_var_and_attv_nums(template_size, attv_num, tmp);
00354   answer_template = answer_template - template_size;
00355 
00356   /* Now `answer_template' points to the mth term */
00357   /* Initialize var_regs[] as the attvs in the call. */
00358   num_vars_in_var_regs = -1;
00359   if (attv_num > 0) {
00360     CPtr cptr;
00361     for (cptr = answer_template + template_size - 1;
00362          cptr >= answer_template; cptr--) {
00363       if (isattv(cell(cptr)))
00364         var_regs[++num_vars_in_var_regs] = (CPtr) cell(cptr);
00365     }
00366     /* now num_vars_in_var_regs should be attv_num - 1 */
00367   }
00368   
00369   reg_arrayptr = reg_array - 1;
00370   for (tmp = 0; tmp < template_size; tmp++) {
00371     CPtr cptr = answer_template;
00372     pushreg(*cptr);
00373     answer_template++;
00374   }
00375   /* backtrack to prev tabled subgoal after returning answers */
00376   breg = tcp_prevbreg(orig_breg);
00377   delay_it = 1; /* run delay lists, don't construct them */
00378 }
00379 
00380 #endif /* LOCAL_EVAL */
00381 #endif /* __COMPLETE_LOCAL_H__ */

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