slginsts_xsb_i.h

00001 /* File:      slginsts_xsb_i.h
00002 ** Author(s): Swift, Rao, Sagonas, Freire, Cui, Johnson
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: slginsts_xsb_i.h,v 1.59 2006/06/02 23:32:39 ruim Exp $
00022 ** 
00023 */
00024 
00025 
00026 /* special debug includes */
00027 #include "debugs/debug_delay.h"
00028 
00029 
00030 #define ARITY   op1     /* register Cell */
00031 #define Yn      op2     /* register Cell */
00032 #define LABEL   op3     /* CPtr */
00033 
00034 /*-------------------------------------------------------------------------*/
00035 
00036 /*
00037  *  Organization of Tabling Choice Points:
00038  *
00039  *             +-------------+
00040  *             |             |   LOW MEMORY
00041  *             |    Trail    |
00042  *             |             |
00043  *             |      |      |
00044  *             |      V      |
00045  *             |             |
00046  *             |             |
00047  *             |      ^      |
00048  *             |      |      |
00049  *             |             |
00050  *             |  CP Stack   |
00051  *             |             |
00052  *             |             |
00053  *             |=============|
00054  *             | Rest of CPF |--- Different for Generator and Consumer
00055  *             |-------------|_
00056  *             |   INT: m    | \
00057  *             |   Term-m    |  |
00058  *             |      .      |  |- Answer Template
00059  *             |      .      |  |
00060  *             |      .      |  |
00061  *             |   Term-1    |_/
00062  *             |=============|
00063  *             |      .      |
00064  *             |      .      |
00065  *             |      .      |    HIGH MEMORY
00066  *             +-------------+
00067  *
00068  *
00069  *  Answer Templates are stored in the Heap:
00070  *
00071  *             +-------------+
00072  *             |      .      |   LOW MEMORY
00073  *             |      .      |
00074  *             |      .      |
00075  *             |-------------|_
00076  *             |   Term-m    | \
00077  *             |      .      |  |
00078  *             |      .      |  |- Answer Template
00079  *             |      .      |  |
00080  *             |   Term-1    |  |
00081  *             |   INT: m    |_/
00082  *             |-------------|
00083  *             |             |
00084  *             |    Heap     |
00085  *             |             |
00086  *             |      |      |
00087  *             |      V      |
00088  *             |             |
00089  *             |             |
00090  *             |      ^      |
00091  *             |      |      |
00092  *             |             |
00093  *             |    Local    |
00094  *             |             |    HIGH MEMORY
00095  *             +-------------+
00096  */
00097 
00098 /*-------------------------------------------------------------------------*/
00099 
00100 /*
00101  *  Instruction format:
00102  *    1st word: opcode X X pred_arity
00103  *    2nd word: pred_first_clause_label
00104  *    3rd word: preds_TableInfo_record
00105  */
00106 
00107 XSB_Start_Instr_Chained(tabletry,_tabletry)
00108 XSB_Start_Instr(tabletrysingle,_tabletrysingle) 
00109   DefOps13
00110   /*
00111    *  Retrieve instruction arguments and test the system stacks for
00112    *  overflow.  The local PCreg, "lpcreg", is incremented to point to
00113    *  the instruction to be executed should this one fail.
00114    */
00115   byte this_instr = *lpcreg;
00116   byte *continuation;
00117   TabledCallInfo callInfo;
00118   CallLookupResults lookupResults;
00119   VariantSF producer_sf, consumer_sf;
00120   CPtr answer_template;
00121   int template_size, attv_num, tmp;
00122   TIFptr tip;
00123 #ifdef SHARED_COMPL_TABLES
00124   byte * inst_addr = lpcreg;
00125   int table_tid ;
00126   int grabbed = FALSE;
00127   th_context * waiting_for_thread;
00128 #endif
00129 #ifdef MULTI_THREAD_RWL
00130   CPtr tbreg;
00131 #ifdef SLG_GC
00132   CPtr old_cptop;
00133 #endif
00134 #endif
00135 
00136   xwammode = 1;
00137   CallInfo_Arguments(callInfo) = reg + 1;
00138   CallInfo_CallArity(callInfo) = get_xxa; 
00139   LABEL = (CPtr)((byte *) get_xxxl);  
00140   Op1(get_xxxxl);
00141   tip =  (TIFptr) get_xxxxl;
00142   SET_TRIE_ALLOCATION_TYPE_TIP(tip); /* No-op in seq engine */
00143 #ifdef MULTI_THREAD
00144   handle_dispatch_block(tip);
00145 #endif
00146   CallInfo_TableInfo(callInfo) = tip;
00147   ADVANCE_PC(size_xxxXX);
00148 
00149   check_tcpstack_overflow;
00150   CallInfo_VarVectorLoc(callInfo) = top_of_cpstack;
00151 
00152   if ( this_instr == tabletry ) {
00153     /* lpcreg was left pointing to the next clause, e.g. tableretry */
00154     continuation = lpcreg;
00155   }
00156   else 
00157     continuation = (pb) &check_complete_inst;
00158 
00159   check_glstack_overflow(CallInfo_CallArity(callInfo),lpcreg,OVERFLOW_MARGIN);
00160 
00161 #ifdef SHARED_COMPL_TABLES
00162   pthread_mutex_lock( &completing_mut );
00163 #endif
00164   /*
00165    *  Perform a call-check/insert operation on the current call.  The
00166    *  subterms of this call which form the answer template are
00167    *  computed and pushed on top of the CP stack, along with its size
00168    *  (encoded as a Prolog INT) .  A pointer to this size, followed by
00169    *  the reverse template vector (as depicted above), is returned in
00170    *  CallLUR_VarVector(lookupResults).  Always (now) the answer
00171    *  template is pushed on the Heap rather than the CPS.  In that
00172    *  case, (heap - 1) points to the A.T. and
00173    *  CallLUR_VarVector(lookupResults) has the same value as
00174    *  CallInfo_VarVectorLoc(callInfo).
00175    */
00176   table_call_search(CTXTc &callInfo,&lookupResults);
00177 
00178   producer_sf = CallLUR_Subsumer(lookupResults);
00179   answer_template = CallLUR_VarVector(lookupResults);
00180 
00181 xsb_dbgmsg((LOG_DEBUG,"After variant call search AT: %x\n",answer_template));
00182 
00183 #ifdef SHARED_COMPL_TABLES
00184 /* This allows sharing of completed tables.
00185    If the subgoal frame is not new, and the table is being generated by
00186    a different thread, wait for it to complete.
00187  */
00188   if ( !IsNULL(producer_sf) ) {
00189      while( !is_completed(producer_sf))
00190      {  
00191         /* if is leader and subgoal is marked to be computed by leader */
00192         if( th->deadlock_brk_leader && subg_grabbed(producer_sf) )
00193         {       subg_tid(producer_sf) = th->tid ;
00194                 subg_grabbed(producer_sf) = FALSE ;
00195                 grabbed = TRUE ;
00196                 break ;
00197         }
00198         table_tid = subg_tid(producer_sf) ;
00199         /* if the thread owns the table, proceed */
00200         if (table_tid == th->tid) 
00201                 break ;
00202         waiting_for_thread = find_context(table_tid) ;
00203         if( would_deadlock( waiting_for_thread, th ) )
00204         {       /* code for leader */
00205                 reset_other_threads( th, waiting_for_thread, producer_sf );
00206                 th->deadlock_brk_leader = TRUE ;
00207                 continue ;
00208         }
00209         th->waiting_for_subgoal = producer_sf ;
00210         th->waiting_for_thread = waiting_for_thread ;
00211         pthread_cond_wait(&completing_cond,&completing_mut) ;
00212         if( th->reset_thread )
00213         {       th->reset_thread = FALSE ;
00214                 pthread_mutex_unlock(&completing_mut) ;
00215                 /* restart the tabletry instruction */
00216                 lpcreg = pcreg ;
00217                 XSB_Next_Instr() ;
00218         }
00219      }
00220      th->waiting_for_thread = NULL ;
00221      th->waiting_for_subgoal = NULL ;
00222      pthread_mutex_unlock(&completing_mut);
00223   } 
00224 
00225   if ( IsNULL(producer_sf) || grabbed ) {
00226 
00227     /* New Producer
00228        ------------ */
00229     CPtr producer_cpf;
00230     if( !grabbed )
00231     {
00232       producer_sf = NewProducerSF(CTXTc CallLUR_Leaf(lookupResults),
00233                                    CallInfo_TableInfo(callInfo));
00234       subg_tid(producer_sf) = th->tid;
00235       subg_grabbed(producer_sf) = 0;
00236       pthread_mutex_unlock( &completing_mut );
00237     }
00238     else
00239     {   subg_compl_stack_ptr(producer_sf) = openreg - COMPLFRAMESIZE;
00240     }
00241 #else  /* !SHARED_COMPL_TABLES */
00242 #ifdef CONC_COMPL
00243     pthread_mutex_lock( &completing_mut ) ;
00244 #endif
00245   if ( IsNULL(producer_sf) ) {
00246 #ifdef CONC_COMPL
00247     pthread_mutex_unlock( &completing_mut ) ;
00248 #endif
00249 
00250     /* New Producer
00251        ------------ */
00252     CPtr producer_cpf;
00253     producer_sf = NewProducerSF(CTXTc CallLUR_Leaf(lookupResults),
00254                                  CallInfo_TableInfo(callInfo));
00255 #endif /* !SHARED_COMPL_TABLES */
00256 #ifdef CONC_COMPL
00257     subg_tid(producer_sf) = th->tid;
00258     subg_tag(producer_sf) = INCOMP_ANSWERS;
00259 #endif
00260     producer_cpf = answer_template;
00261     save_find_locx(ereg);
00262     save_registers(producer_cpf, CallInfo_CallArity(callInfo), rreg);
00263     SaveProducerCPF(producer_cpf, continuation, producer_sf,
00264                     CallInfo_CallArity(callInfo), (hreg - 1));
00265 #ifdef SHARED_COMPL_TABLES
00266     tcp_reset_pcreg(producer_cpf) = inst_addr ;
00267 #endif
00268 #ifdef SLG_GC
00269     tcp_prevtop(producer_cpf) = answer_template; 
00270     /* answer_template points to the previous top, since the A.T. proper
00271        is now always copied to the heap */
00272 #endif
00273     push_completion_frame(producer_sf);
00274 #ifdef CONC_COMPL
00275     compl_ext_cons(openreg) = NULL ;
00276     tcp_compl_stack_ptr(producer_cpf) = openreg ;
00277 #endif
00278     ptcpreg = (CPtr)producer_sf;
00279     subg_cp_ptr(producer_sf) = breg = producer_cpf;
00280     xsb_dbgmsg((LOG_COMPLETION,"just created tabled cp %x\n",breg));
00281     delayreg = NULL;
00282     if (root_address == 0)
00283       root_address = breg;
00284     hbreg = hreg;
00285     lpcreg = (byte *) LABEL;    /* branch to program clause */
00286     XSB_Next_Instr();
00287   }
00288 
00289   else if ( is_completed(producer_sf) ) {
00290 
00291 #ifdef CONC_COMPL
00292     pthread_mutex_unlock( &completing_mut ) ;
00293 #endif
00294     /* Unify Call with Answer Trie
00295        --------------------------- */
00296     if (has_answer_code(producer_sf)) {
00297       int i;
00298       xsb_dbgmsg((LOG_DELAY, "++Returning answers from COMPLETED table: "));
00299       dbg_print_subgoal(LOG_DELAY, stddbg, producer_sf);
00300       xsb_dbgmsg((LOG_DELAY, "\n"));
00301       answer_template = hreg - 1; 
00302 
00303       tmp = int_val(cell(answer_template));
00304       get_var_and_attv_nums(template_size, attv_num, tmp);
00305       num_vars_in_var_regs = -1;
00306 
00307       /* Initialize var_regs[] as the attvs in the call.  This is
00308          needed by the trie_xxx_val instructions, and the symbols of
00309          the trie nodes have been set up to account for this in
00310          variant_answer_search() -- see the documentation there.  */
00311       if (attv_num > 0) {
00312         CPtr cptr;
00313         for (cptr = answer_template - 1;
00314              cptr >= answer_template - template_size; cptr--) {
00315           // tls changed from 10/05 cptr >= answer_template + template_size; cptr++) 
00316           if (isattv(cell(cptr))) {
00317             var_regs[++num_vars_in_var_regs] = (CPtr) cell(cptr);
00318             xsb_dbgmsg((LOG_TRIE_INSTR, "setting var_regs for attv %d \n",
00319                         num_vars_in_var_regs));
00320           }
00321         }
00322         /* now num_vars_in_var_regs should be attv_num - 1 */
00323       }
00324 
00325       reg_arrayptr = reg_array-1;
00326       for (i = 0; i < template_size; i++) {
00327         pushreg(cell(answer_template-template_size+i));
00328       }
00329       delay_it = 1;
00330       lpcreg = (byte *)subg_ans_root_ptr(producer_sf);
00331 #ifdef MULTI_THREAD_RWL
00332 /* save choice point for trie_unlock instruction */
00333       save_find_locx(ereg);
00334       tbreg = top_of_cpstack;
00335 #ifdef SLG_GC
00336       old_cptop = tbreg;
00337 #endif
00338       save_choicepoint(tbreg,ereg,(byte *)&trie_fail_unlock_inst,breg);
00339 #ifdef SLG_GC
00340       cp_prevtop(tbreg) = old_cptop;
00341 #endif
00342       breg = tbreg;
00343       hbreg = hreg;
00344 #endif
00345       XSB_Next_Instr();
00346     }
00347     else {
00348       Fail1;
00349       XSB_Next_Instr();
00350     }
00351   }
00352 
00353   else if ( CallLUR_VariantFound(lookupResults) )
00354 
00355     /* Previously Seen Subsumed Call
00356        ----------------------------- */
00357     consumer_sf = CallTrieLeaf_GetSF(CallLUR_Leaf(lookupResults));
00358 
00359   else
00360 
00361     /* New Properly Subsumed Call
00362        -------------------------- */
00363     NewSubConsSF( consumer_sf, CallLUR_Leaf(lookupResults),
00364                    CallInfo_TableInfo(callInfo), producer_sf );
00365 
00366   /*
00367    * The call, represented by "consumer_sf", will consume from an
00368    * incomplete producer, represented by "producer_sf".
00369    */
00370   {
00371     CPtr consumer_cpf;
00372 #ifdef SLG_GC
00373     CPtr prev_cptop;
00374 #endif
00375     ALNptr answer_continuation;
00376     BTNptr first_answer;
00377 
00378     /* Create Consumer Choice Point
00379        ---------------------------- */
00380 #ifdef CONC_COMPL
00381     CPtr producer_cpf ;
00382 
00383     if( subg_tid(producer_sf) == th->tid )
00384     {
00385 #endif
00386     adjust_level(subg_compl_stack_ptr(producer_sf));
00387 #ifdef CONC_COMPL
00388     consumer_cpf = answer_template;
00389     }
00390     else
00391     {
00392         producer_cpf = answer_template;
00393         SaveProducerCPF(producer_cpf, (pb)&check_complete_inst, producer_sf,
00394                         CallInfo_CallArity(callInfo), (hreg - 1));
00395         consumer_cpf = breg = producer_cpf;
00396     }
00397 #endif
00398     save_find_locx(ereg);
00399 
00400 #ifndef CONC_COMPL
00401     consumer_cpf = answer_template;
00402 #endif
00403 #ifdef SLG_GC
00404     prev_cptop = consumer_cpf;
00405 #endif
00406 
00407     answer_template = hreg-1;
00408 
00409     efreg = ebreg;
00410     if (trreg > trfreg) trfreg = trreg;
00411     if (hfreg < hreg) hfreg = hreg;
00412     SaveConsumerCPF( consumer_cpf, consumer_sf,
00413                      subg_asf_list_ptr(producer_sf), 
00414                      answer_template);
00415 #ifdef SLG_GC
00416     nlcp_prevtop(consumer_cpf) = prev_cptop;
00417 #endif
00418     subg_asf_list_ptr(producer_sf) = breg = bfreg = consumer_cpf;
00419 
00420     xsb_dbgmsg((LOG_COMPLETION,"created ccp at %x with prevbreg as %x\n",
00421                 breg,nlcp_prevbreg(breg)));
00422 
00423 #ifdef CONC_COMPL
00424     nlcp_tid(consumer_cpf) = makeint(th->tid);
00425 
00426     if( subg_tid(producer_sf) != th->tid )
00427     {
00428         push_completion_frame(producer_sf);
00429         compl_ext_cons(openreg) = consumer_cpf;
00430         tcp_compl_stack_ptr(producer_cpf) = openreg ;
00431     }
00432 #endif
00433 
00434     /* Consume First Answer or Suspend
00435        ------------------------------- */
00436     table_pending_answer( subg_ans_list_ptr(consumer_sf),
00437                           answer_continuation,
00438                           first_answer,
00439                           (SubConsSF)consumer_sf,
00440                           (SubProdSF)producer_sf,
00441                           answer_template,
00442                           TPA_NoOp,
00443                           TPA_NoOp );
00444 
00445     if ( IsNonNULL(answer_continuation) ) {
00446       int tmp;
00447       nlcp_trie_return(consumer_cpf) = answer_continuation; 
00448       hbreg = hreg;
00449 
00450       tmp = int_val(cell(answer_template));
00451       get_var_and_attv_nums(template_size, attv_num, tmp);
00452       answer_template--;
00453 
00454       table_consume_answer(CTXTc first_answer,template_size,attv_num,answer_template,
00455                            CallInfo_TableInfo(callInfo));
00456 
00457       if (is_conditional_answer(first_answer)) {
00458         xsb_dbgmsg((LOG_DELAY,
00459                 "! POSITIVELY DELAYING in lay active (delayreg = %p)\n",
00460                 delayreg));
00461         xsb_dbgmsg((LOG_DELAY, "\n>>>> delay_positively in lay_down_active\n"));
00462         xsb_dbgmsg((LOG_DELAY, ">>>> subgoal = "));
00463         dbg_print_subgoal(LOG_DELAY, stddbg, producer_sf);
00464         xsb_dbgmsg((LOG_DELAY, "\n"));
00465         {
00466           /*
00467            * Similar to delay_positively() in retry_active, we also
00468            * need to put the substitution factor of the answer,
00469            * var_addr[], into a term ret/n and pass it to
00470            * delay_positively().
00471            */
00472           if (num_heap_term_vars == 0) {
00473             delay_positively(producer_sf, first_answer,
00474                              makestring(get_ret_string()));
00475           }
00476           else {
00477 #ifndef IGNORE_DELAYVAR
00478             int i;
00479             CPtr temp_hreg = hreg;
00480             new_heap_functor(hreg, get_ret_psc(num_heap_term_vars));
00481             if (var_addr == NULL) printf("var_addr NULL 3\n");
00482             for (i = 0; i < num_heap_term_vars; i++)
00483               cell(hreg++) = (Cell) var_addr[i];
00484             delay_positively(producer_sf, first_answer, makecs(temp_hreg));
00485 #else
00486             delay_positively(producer_sf, first_answer,
00487                              makestring(get_ret_string()));
00488 #endif /* IGNORE_DELAYVAR */
00489           }
00490         }
00491       }
00492       lpcreg = cpreg;
00493     }
00494     else {
00495       breg = nlcp_prevbreg(consumer_cpf);
00496       Fail1;
00497     }
00498 #ifdef CONC_COMPL
00499     pthread_mutex_unlock(&completing_mut);
00500 #endif
00501   }
00502 XSB_End_Instr()
00503 
00504 /*-------------------------------------------------------------------------*/
00505 
00506 /*
00507  *  Instruction format:
00508  *    1st word: opcode X X X
00509  *
00510  *  Description:
00511  *    Returns to a consumer an answer if one is available, otherwise it
00512  *    suspends.  Answer consumption is effected by unifying the consumer's
00513  *    answer template with an answer.  This instruction is encountered only
00514  *    by backtracking into a consumer choice point frame, either as a
00515  *    result of WAM- style backtracking or having been resumed via a
00516  *    check-complete instruction.  The CPF field "nlcp-trie-return" points
00517  *    to the last answer consumed.  If none have yet been consumed, then it
00518  *    points to the dummy answer.
00519  */
00520 
00521 XSB_Start_Instr(answer_return,_answer_return) 
00522   VariantSF consumer_sf;
00523   ALNptr answer_continuation;
00524   BTNptr next_answer;
00525   CPtr answer_template;
00526   int template_size, attv_num;
00527 
00528 
00529   xsb_dbgmsg((LOG_DEBUG,"Starting answer return %x (%x) (prev %x)\n",
00530               breg,*lpcreg,nlcp_prevbreg(breg))); 
00531 
00532   /* Locate relevant answers
00533      ----------------------- */
00534   answer_continuation = ALN_Next(nlcp_trie_return(breg)); /* step to next answer */
00535   consumer_sf = (VariantSF)nlcp_subgoal_ptr(breg);
00536   answer_template = nlcp_template(breg);
00537 #ifdef CONC_COMPL
00538   pthread_mutex_lock(&completing_mut);
00539 #endif
00540   table_pending_answer( nlcp_trie_return(breg),
00541                         answer_continuation,
00542                         next_answer,
00543                         (SubConsSF)consumer_sf,
00544                         conssf_producer(consumer_sf),
00545                         answer_template,
00546                         switch_envs(breg),
00547                         TPA_NoOp );
00548 
00549   if ( IsNonNULL(answer_continuation)) {
00550     int tmp;
00551 
00552     /* Restore Consumer's state
00553        ------------------------ */
00554     switch_envs(breg);
00555     ptcpreg = nlcp_ptcp(breg);
00556     delayreg = nlcp_pdreg(breg);
00557     restore_some_wamregs(breg, ereg);
00558 
00559     /* Consume the next answer
00560        ----------------------- */
00561     nlcp_trie_return(breg) = answer_continuation;   /* update */
00562     tmp = int_val(cell(answer_template));
00563     get_var_and_attv_nums(template_size, attv_num, tmp);
00564     answer_template--;
00565 
00566     //    printf("answer_template %x size %d\n",answer_template,template_size);
00567     //    sfPrintGoal(CTXTdeclc stddbg, consumer_sf, FALSE);
00568 
00569     table_consume_answer(CTXTc next_answer,template_size,attv_num,answer_template,
00570                          subg_tif_ptr(consumer_sf));
00571 
00572     if (is_conditional_answer(next_answer)) {
00573       /*
00574        * After load_solution_trie(), the substitution factor of the
00575        * answer is left in array var_addr[], and its arity is in
00576        * num_heap_term_vars.  We have to put it into a term ret/n (on 
00577        * the heap) and pass it to delay_positively().
00578        */
00579       if (num_heap_term_vars == 0) {
00580         delay_positively(consumer_sf, next_answer,
00581                          makestring(get_ret_string()));
00582       }
00583       else {
00584 #ifndef IGNORE_DELAYVAR
00585         int i;
00586         CPtr temp_hreg = hreg;
00587         new_heap_functor(hreg, get_ret_psc(num_heap_term_vars));
00588         if (var_addr == NULL) printf("var_addr NULL 4\n");
00589         for (i = 0; i < num_heap_term_vars; i++) {
00590           cell(hreg++) = (Cell) var_addr[i];
00591         }
00592         delay_positively(consumer_sf, next_answer, makecs(temp_hreg));
00593 #else
00594         delay_positively(consumer_sf, next_answer,
00595                          makestring(get_ret_string()));
00596 #endif /* IGNORE_DELAYVAR */
00597       }
00598     }
00599     lpcreg = cpreg;
00600   }
00601 
00602   else {
00603 
00604     /* Suspend this Consumer
00605        --------------------- */
00606     xsb_dbgmsg((LOG_DEBUG,"Failing from answer return %x to %x (inst %x)\n",
00607                 breg,nlcp_prevbreg(breg),*tcp_pcreg(nlcp_prevbreg(breg))));
00608     breg = nlcp_prevbreg(breg); /* in semi-naive this execs next active */
00609     restore_trail_condition_registers(breg);
00610     if (hbreg >= hfreg) hreg = hbreg; else hreg = hfreg;
00611     Fail1;
00612   }
00613 #ifdef CONC_COMPL
00614   pthread_mutex_unlock(&completing_mut);
00615 #endif
00616 XSB_End_Instr()
00617 
00618 /*-------------------------------------------------------------------------*/
00619 
00620 /*
00621  *  Instruction format:
00622  *    1st word: opcode X pred_arity perm_var_index
00623  *
00624  *  Description:
00625  *    Last instruction in each clause of a tabled predicate.  The instruction
00626  *    (1) saves the answer substitution in the answer trie and (2)
00627  *    adds a cell to the end of the answer list pointing to the root
00628  *    of the new subtstitution. All the
00629  *    information necessary to perform this Answer Check/Insert operation
00630  *    is saved in the producer's choice point frame.  This CP is 
00631  *    reached through the subgoal frame, which is noted in the first
00632  *    environment variable of the tabled clause.
00633  * 
00634  *    In the case where we have added an unconditional ground answer
00635  *    we perform early completion for the subgoal.
00636  *
00637  *    Next, if we are executing Local Evaluation, we fail after adding
00638  *    the answer (and perhaps performing ec)  This is not always the
00639  *    optimal way, as we need fail only if the subgoal is potentially
00640  *    a leader.
00641  * 
00642  *    If we are not executing local evaluation, we take the forward
00643  *    condinuation (i.e. we'll proceed).  In his case a delay element
00644  *    must be added to the delay list or the root subgoal of the
00645  *    current subgoal before proceeding.
00646  */
00647 
00648 XSB_Start_Instr(new_answer_dealloc,_new_answer_dealloc) 
00649   Def2ops
00650   CPtr producer_cpf, producer_csf, answer_template;
00651   int template_size, attv_num, tmp;
00652   VariantSF producer_sf;
00653   xsbBool isNewAnswer = FALSE;
00654   BTNptr answer_leaf;
00655 
00656   ARITY = get_xax;
00657   Yn = get_xxa; /* we want the # of the register, not a pointer to it */
00658 
00659   ADVANCE_PC(size_xxx);
00660 
00661   xsb_dbgmsg((LOG_COMPLETION,"starting new_answer breg %x\n",breg));
00662   producer_sf = (VariantSF)cell(ereg-Yn);
00663   producer_cpf = subg_cp_ptr(producer_sf);
00664 
00665 #ifdef DEBUG_DELAYVAR
00666   xsb_dbgmsg((LOG_DEBUG,">>>> New answer for %s subgoal: ",
00667              (is_completed(producer_sf) ? "completed" : "incomplete")));
00668   fprintf(stddbg, ">>>> ");
00669   dbg_print_subgoal(LOG_DEBUG, stddbg, producer_sf);
00670   xsb_dbgmsg((LOG_DEBUG,">>>> has delayreg = %p", delayreg));
00671 #endif
00672 
00673   producer_csf = subg_compl_stack_ptr(producer_sf);
00674 
00675   /* if the subgoal has been early completed and its space reclaimed
00676    * from the stacks, access to its relevant information (e.g. to its
00677    * substitution factor) in the stacks is not safe, so better not
00678    * try to add this answer; it is a redundant one anyway...
00679    */
00680   if ((subgoal_space_has_been_reclaimed(producer_sf,producer_csf)) ||
00681       (IsNonNULL(delayreg) && answer_is_junk(delayreg))) {
00682     Fail1;
00683     XSB_Next_Instr();
00684   }
00685 
00686   /* answer template is now in the heap for generators */
00687   answer_template = tcp_template(subg_cp_ptr(producer_sf));
00688   tmp = int_val(cell(answer_template));
00689   get_var_and_attv_nums(template_size, attv_num, tmp);
00690   answer_template--;
00691 
00692 #ifdef DEBUG_DELAYVAR
00693   xsb_dbgmsg(LOG_DEBUG,">>>> ARITY = %d; Yn = %d", (int)ARITY, (int)Yn);
00694 #endif
00695 
00696   xsb_dbgmsg((LOG_DELAY, "\t--> This answer for "));
00697   dbg_print_subgoal(LOG_DELAY, stddbg, producer_sf);
00698 #ifdef DEBUG_VERBOSE
00699   if (LOG_DELAY <= cur_log_level) {
00700     if (delayreg != NULL) {
00701       fprintf(stddbg, " has delay list = ");
00702       print_delay_list(stddbg, delayreg);
00703     } else {
00704       fprintf(stddbg, " has no delay list\n");
00705     }
00706   }
00707 #endif
00708 
00709 #ifdef DEBUG_DELAYVAR
00710   fprintf(stddbg, "\n>>>> (before variant_answer_search) template_size = %d\n",
00711           (int)template_size);
00712   {
00713     int i;
00714     for (i = 0; i < template_size; i++) {
00715       fprintf(stddbg, ">>>> answer_template[%d] = ", i);
00716       printterm(stddbg, (Cell)(answer_template - i), 25);
00717       fprintf(stddbg, "\n");
00718     }
00719   }
00720 #endif
00721 
00722   SET_TRIE_ALLOCATION_TYPE_SF(producer_sf); /* No-op in seq engine */
00723   answer_leaf = table_answer_search( CTXTc producer_sf, template_size, attv_num,
00724                                      answer_template, &isNewAnswer );
00725 
00726   if ( isNewAnswer ) {   /* go ahead -- look for more answers */
00727     delayreg = tcp_pdreg(producer_cpf);      /* restore delayreg of parent */
00728     if (is_conditional_answer(answer_leaf)) {   /* positive delay */
00729 #ifndef LOCAL_EVAL
00730 #ifdef DEBUG_DELAYVAR
00731       fprintf(stddbg, ">>>> delay_positively in new_answer_dealloc\n");
00732 #endif
00733       /*
00734        * The new answer for this call is a conditional one, so add it
00735        * into the delay list for its root subgoal.  Notice that
00736        * delayreg has already been restored to the delayreg of parent.
00737        *
00738        * This is the new version of delay_positively().  Here,
00739        * ans_var_pos_reg is passed from variant_answer_search().  It is a
00740        * pointer to the heap where the substitution factor of the
00741        * answer was saved as a term ret/n (in variant_answer_search()).
00742        */
00743 #ifndef IGNORE_DELAYVAR
00744       if (isinteger(cell(ans_var_pos_reg))) {
00745         delay_positively(producer_sf, answer_leaf,
00746                          makestring(get_ret_string()));
00747       }
00748       else 
00749         delay_positively(producer_sf, answer_leaf, makecs(ans_var_pos_reg));
00750 #else
00751         delay_positively(producer_sf, answer_leaf,
00752                          makestring(get_ret_string()));
00753 #endif /* IGNORE_DELAYVAR */
00754 #endif /* ! LOCAL_EVAL */
00755     }
00756     else {
00757       if (template_size == 0) {
00758         /*
00759          *  The table is for a ground call which we just proved true.
00760          *  (We entered an ESCAPE Node, above, to note this fact in the
00761          *  table.)  As we only need to do this once, we perform "early
00762          *  completion" by ignoring the other clauses of the predicate
00763          *  and setting the failure continuation (next_clause) field of
00764          *  the CPF to a check_complete instr.
00765          *
00766          */
00767         perform_early_completion(producer_sf, producer_cpf);
00768 #if defined(LOCAL_EVAL)
00769           breg = producer_cpf;
00770 #endif
00771       }
00772     }
00773 #ifdef LOCAL_EVAL
00774     Fail1;      /* and do not return answer to the generator */
00775     xsb_dbgmsg((LOG_DEBUG,"Failing from new answer %x to %x (inst %x)\n",
00776                 breg,tcp_pcreg(breg),*tcp_pcreg(breg)));
00777 
00778 #else
00779     ptcpreg = tcp_ptcp(producer_cpf);
00780     cpreg = *((byte **)ereg-1);
00781     ereg = *(CPtr *)ereg;
00782     lpcreg = cpreg; 
00783 #endif
00784   }
00785   else     /* repeat answer -- ignore */
00786      Fail1;
00787 XSB_End_Instr()
00788 
00789 /*-------------------------------------------------------------------------*/
00790 
00791 /*
00792  *  Instruction format:
00793  *    1st word: opcode X X pred_arity
00794  *    2nd word: pred_next_clause_label
00795  *
00796  *  Description:
00797  *    Store the predicate's arity in "op1", update the failure continuation
00798  *    to the instruction following this one, and set the program counter to
00799  *    the predicate's next code subblock to be executed, as pointed to by
00800  *    the second argument to this instruction.  Finally, restore the state
00801  *    at the point of choice and continue execution using the predicate's
00802  *    next code subblock.
00803  */
00804 
00805 XSB_Start_Instr(tableretry,_tableretry)
00806   Def1op
00807   Op1(get_xxa);
00808   tcp_pcreg(breg) = lpcreg+sizeof(Cell)*2;
00809   lpcreg = *(pb *)(lpcreg+sizeof(Cell));
00810   restore_type = 0;
00811   TABLE_RESTORE_SUB
00812 XSB_End_Instr()
00813 
00814 /*-------------------------------------------------------------------------*/
00815 
00816 /*
00817  *  Instruction format:
00818  *    1st word: opcode X X pred_arity
00819  *
00820  *  Description:
00821  *    Store the predicate's arity in "op1", update the failure continuation
00822  *    to a check_complete instruction, and set the program counter to the
00823  *    predicate's last code subblock to be executed, as pointed to by the
00824  *    second argument to this instruction.  Finally, restore the state at
00825  *    the point of choice and continue execution with this last code
00826  *    subblock.
00827  */
00828 
00829 XSB_Start_Instr(tabletrust,_tabletrust)
00830   Def1op
00831   Op1(get_xxa);
00832   ADVANCE_PC(size_xxx);
00833   tcp_pcreg(breg) = (byte *) &check_complete_inst;
00834   lpcreg = *(pb *)lpcreg;
00835 #if defined(LOCAL_EVAL)
00836   /* trail cond. registers should not be restored here for Local */
00837   restore_type = 0;
00838 #else
00839   restore_type = 1;
00840 #endif
00841   TABLE_RESTORE_SUB
00842 XSB_End_Instr()
00843 /*-------------------------------------------------------------------------*/
00844 
00845 #include "complete_xsb_i.h"
00846 
00847 /*-------------------------------------------------------------------------*/
00848 
00849 XSB_Start_Instr(resume_compl_suspension,_resume_compl_suspension)
00850 #ifdef DEBUG_DELAYVAR
00851       fprintf(stddbg, ">>>> resume_compl_suspension is called\n");
00852 #endif
00853 {
00854   if ((unsigned long) csf_pcreg(breg) == 
00855       (unsigned long) &resume_compl_suspension_inst) {
00856     CPtr csf = breg;
00857     
00858     /* Switches the environment to a frame of a subgoal that was        */
00859     /* suspended on completion, and sets the continuation pointer.      */
00860     check_glstack_overflow(0,lpcreg,OVERFLOW_MARGIN);
00861     freeze_and_switch_envs(csf, COMPL_SUSP_CP_SIZE);
00862     ptcpreg = csf_ptcp(csf);
00863     neg_delay = (csf_neg_loop(csf) != FALSE);
00864     delayreg = csf_pdreg(csf);
00865     cpreg = csf_cpreg(csf); 
00866     ereg = csf_ereg(csf);
00867     ebreg = csf_ebreg(csf);
00868     hbreg = csf_hreg(csf);
00869     save_find_locx(ereg);
00870     hbreg = hreg;
00871     breg = csf_prevcsf(csf);
00872     lpcreg = cpreg;
00873   } else {
00874     CPtr csf = cs_compsuspptr(breg);
00875     /* Switches the environment to a frame of a subgoal that was        */
00876     /* suspended on completion, and sets the continuation pointer.      */
00877     check_glstack_overflow(0,lpcreg,OVERFLOW_MARGIN);
00878     freeze_and_switch_envs(csf, COMPL_SUSP_CP_SIZE);
00879     ptcpreg = csf_ptcp(csf);
00880     neg_delay = (csf_neg_loop(csf) != FALSE);
00881     delayreg = csf_pdreg(csf);
00882     cpreg = csf_cpreg(csf); 
00883     ereg = csf_ereg(csf);
00884     ebreg = csf_ebreg(csf);
00885     hbreg = csf_hreg(csf);
00886     save_find_locx(ereg);
00887     hbreg = hreg;
00888     if (csf_prevcsf(csf) != NULL) {
00889       cs_compsuspptr(breg) = csf_prevcsf(csf);
00890     } else {
00891       breg = cs_prevbreg(breg);
00892     }
00893     lpcreg = cpreg;
00894   }
00895 }
00896 XSB_End_Instr()
00897 
00898 /*----------------------------------------------------------------------*/
00899 

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