~burner/xsb/debianized-xsb

« back to all changes in this revision

Viewing changes to emu/wfs_xsb_i.h

  • Committer: Michael R. Head
  • Date: 2006-09-06 22:11:55 UTC
  • Revision ID: burner@n23-20060906221155-7e398d23438a7ee4
Add the files from the 3.0.1 release package

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* File:      wfs_xsb_i.h
 
2
** Author(s): Kostis Sagonas
 
3
** Documentation added by TLS 02/02
 
4
** Contact:   xsb-contact@cs.sunysb.edu
 
5
** 
 
6
** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
 
7
** 
 
8
** XSB is free software; you can redistribute it and/or modify it under the
 
9
** terms of the GNU Library General Public License as published by the Free
 
10
** Software Foundation; either version 2 of the License, or (at your option)
 
11
** any later version.
 
12
** 
 
13
** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
 
14
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
15
** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
 
16
** more details.
 
17
** 
 
18
** You should have received a copy of the GNU Library General Public License
 
19
** along with XSB; if not, write to the Free Software Foundation,
 
20
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
21
**
 
22
** $Id: wfs_xsb_i.h,v 1.15 2005/11/16 17:32:06 dwarren Exp $
 
23
** 
 
24
*/
 
25
 
 
26
 
 
27
/* special debug includes */
 
28
#include "debugs/debug_delay.h"
 
29
 
 
30
/*----------------------------------------------------------------------*/
 
31
 
 
32
#define unvisit(leader) \
 
33
    for (csf = leader; csf >= (ComplStackFrame)openreg; csf--) \
 
34
      compl_visited(csf) = FALSE
 
35
 
 
36
/*----------------------------------------------------------------------*/
 
37
 
 
38
#define edge_alloc_chunk_size   (1024 * sizeof(struct ascc_edge))
 
39
 
 
40
static char *edge_space_chunk_ptr = NULL;
 
41
 
 
42
static EPtr free_edges = NULL, free_edge_space = NULL, top_edge_space = NULL;
 
43
 
 
44
void abolish_edge_space(void)
 
45
{
 
46
    char *t;
 
47
 
 
48
    while (edge_space_chunk_ptr) {
 
49
      t = *(char **)edge_space_chunk_ptr;
 
50
      mem_dealloc(edge_space_chunk_ptr,edge_alloc_chunk_size+sizeof(Cell),TABLE_SPACE);
 
51
      edge_space_chunk_ptr = t;
 
52
    }
 
53
    free_edges = free_edge_space = top_edge_space = NULL;
 
54
}
 
55
 
 
56
static EPtr alloc_more_edge_space(void)
 
57
{
 
58
    char *t;
 
59
 
 
60
    if ((t = (char *)mem_alloc(edge_alloc_chunk_size+sizeof(Cell),TABLE_SPACE)) == NULL)
 
61
      xsb_abort("No space to allocate more edges for SCC detection");
 
62
    *(char **)t = edge_space_chunk_ptr;
 
63
    edge_space_chunk_ptr = t;
 
64
    free_edge_space = (EPtr)(t+sizeof(Cell));
 
65
    top_edge_space = (EPtr)(t+edge_alloc_chunk_size+sizeof(Cell));
 
66
    return free_edge_space++;
 
67
}
 
68
 
 
69
#define Free_Edge(theEdge) \
 
70
    next_edge(theEdge) = free_edges; \
 
71
    free_edges = theEdge
 
72
 
 
73
#define New_Edge(theEdge,FromEptr,ToNode) \
 
74
    if (free_edges) {\
 
75
      theEdge = free_edges; \
 
76
      free_edges = next_edge(free_edges); \
 
77
    } else { \
 
78
      if (free_edge_space < top_edge_space) { \
 
79
        theEdge = free_edge_space++; \
 
80
      } else { \
 
81
        theEdge = alloc_more_edge_space(); \
 
82
      } \
 
83
    } \
 
84
    edge_to_node(theEdge) = (ComplStackFrame) ToNode; \
 
85
    next_edge(theEdge) = FromEptr; \
 
86
    FromEptr = theEdge
 
87
 
 
88
/* Add a dependency graph edge, and its transpose as long as the
 
89
   parent node csf2 (DG "from" node / DGT "to" node) is not completed
 
90
   and lies within the ASCC */
 
91
 
 
92
#define add_ascc_edges(subgoal,cs_frame,leader_cs_frame)        \
 
93
    csf2 = (ComplStackFrame)subg_compl_stack_ptr(subgoal);      \
 
94
    if (leader_cs_frame >= csf2  && !is_completed(subgoal)) {   \
 
95
      New_Edge(eptr, compl_DGT_edges(cs_frame), csf2);          \
 
96
      New_Edge(eptr, compl_DG_edges(csf2), cs_frame);           \
 
97
    }
 
98
 
 
99
static void reclaim_edge_space(ComplStackFrame csf_ptr)
 
100
{
 
101
    EPtr e, eptr;
 
102
 
 
103
    e = compl_DG_edges(csf_ptr);
 
104
    while (e != NULL) {
 
105
      eptr = e;
 
106
      e = next_edge(e);
 
107
      Free_Edge(eptr);
 
108
    }
 
109
    compl_DG_edges(csf_ptr) = NULL;
 
110
    e = compl_DGT_edges(csf_ptr);
 
111
    while (e != NULL) {
 
112
      eptr = e;
 
113
      e = next_edge(e);
 
114
      Free_Edge(eptr);
 
115
    }
 
116
    compl_DGT_edges(csf_ptr) = NULL;
 
117
}
 
118
 
 
119
/*----------------------------------------------------------------------*/
 
120
/* These macros abstract the fact that SLG-WAM and CHAT construct the   */
 
121
/* subgoal dependency graph by looking at different data structures.    */
 
122
/*----------------------------------------------------------------------*/
 
123
 
 
124
#define first_consumer(SUBG,CSF) (subg_asf_list_ptr(SUBG))
 
125
#define ptcp_of_gen(SUBG,CSF)    ((VariantSF)(tcp_ptcp(subg_cp_ptr(SUBG))))
 
126
#define ptcp_of_cons(CONS_CP)    ((VariantSF)(nlcp_ptcp(CONS_CP)))
 
127
#define ptcp_of_csusp(CSUSP_CP)  ((VariantSF)(csf_ptcp(CSUSP_CP)))
 
128
 
 
129
/*----------------------------------------------------------------------*/
 
130
 
 
131
static inline void construct_dep_graph(CTXTdeclc ComplStackFrame leader_compl_frame)
 
132
{
 
133
    EPtr eptr;
 
134
    CPtr asf, nsf;
 
135
    VariantSF p, source_subg;
 
136
    ComplStackFrame csf1, csf2;
 
137
 
 
138
    csf1 = leader_compl_frame;
 
139
    while (csf1 >= (ComplStackFrame)openreg) {
 
140
      source_subg = compl_subgoal_ptr(csf1);
 
141
      if (!is_completed(source_subg)) {
 
142
        /*--- find the edge of the DepGraph due to the generator node ---*/
 
143
        if ((p = ptcp_of_gen(source_subg,csf1)) != NULL) {
 
144
          add_ascc_edges(p, csf1, leader_compl_frame);
 
145
        }
 
146
        /*--- find the edges of the DepGraph due to the consumers ---*/
 
147
        for (asf = first_consumer(source_subg,csf1);
 
148
             asf != NULL; asf = nlcp_prevlookup(asf)) {
 
149
          if ((p = ptcp_of_cons(asf)) != NULL) {
 
150
            add_ascc_edges(p, csf1, leader_compl_frame);
 
151
          }
 
152
        }
 
153
        /*--- find the edges of the DepGraph due to the suspended nodes ---*/
 
154
        for (nsf = subg_compl_susp_ptr(source_subg);
 
155
             nsf != NULL; nsf = csf_prevcsf(nsf)) {
 
156
          if ((p = ptcp_of_csusp(nsf)) != NULL) {
 
157
            add_ascc_edges(p, csf1, leader_compl_frame);
 
158
          }
 
159
        }
 
160
      }
 
161
      csf1 = (ComplStackFrame)next_compl_frame(csf1);
 
162
    }
 
163
#ifdef VERBOSE_COMPLETION
 
164
    xsb_dbgmsg((LOG_DEBUG,"! Constructed the edges of the DepGraph"));
 
165
#endif
 
166
}
 
167
 
 
168
/*----------------------------------------------------------------------*/
 
169
/* The following function handles negation for Batched Scheduling.      */
 
170
/*----------------------------------------------------------------------*/
 
171
 
 
172
static void batched_compute_wfs(CTXTdeclc CPtr leader_compl_frame, 
 
173
                                CPtr leader_breg, 
 
174
                                VariantSF leader_subg)
 
175
{  
 
176
  CPtr ComplStkFrame; /* CopyFrame */
 
177
  xsbBool sccs_needed;
 
178
  VariantSF curr_subg;
 
179
  CPtr cont_breg = leader_breg;
 
180
 
 
181
/*----------------------------------------------------------------------*/
 
182
  /* Perform a check whether exact completion is needed (sccs_needed).
 
183
     For subgoals that are already marked as (early) completed,
 
184
     preclude their completion suspension frames from ever being
 
185
     secheduled and the memory occupied by their chat areas is
 
186
     properly reclaimed. 
 
187
  */
 
188
 
 
189
  sccs_needed = FALSE;
 
190
  ComplStkFrame = leader_compl_frame;
 
191
  while (ComplStkFrame >= openreg) {
 
192
    curr_subg = compl_subgoal_ptr(ComplStkFrame);
 
193
    if (is_completed(curr_subg)) {
 
194
      subg_compl_susp_ptr(curr_subg) = NULL;
 
195
    } else {
 
196
      if (subg_compl_susp_ptr(curr_subg) != NULL) sccs_needed = TRUE;
 
197
    }
 
198
    ComplStkFrame = next_compl_frame(ComplStkFrame);
 
199
  }
 
200
 
 
201
  /**********************************************************************/
 
202
  /* NOTE: many of the following assume that leader_compl_frame
 
203
   * remains unchanged */
 
204
/*----------------------------------------------------------------------*/
 
205
  /* The general algorithm for exact SCC check is defined in the 1998
 
206
     SLGWAM TOPLAS paper. Below we will 
 
207
 
 
208
     1) Construct a dependency graph (DG) + its transpose (DGT) via
 
209
     construct_dep_graph((ComplStackFrame)leader_compl_frame).  Nodes
 
210
     of this graph are formed via cells in compretion stack frames
 
211
     compl_DG_edges, and compl_DGT_edges.
 
212
     
 
213
     2) Traverse that dependency graph to find an independent SCC,
 
214
     $SCC_1$ This is the combined purpose of DFS_DGT(), unvisit() and
 
215
     find_independent_scc() (see the commentary on DFS_DGT in
 
216
     scc_xsb.c).  At the end of this process, subgoals in the
 
217
     independent SCC have compl_visited marked as TRUE
 
218
 
 
219
     3) Check the independent SCC to see whether there is a negative
 
220
     loop --- non_lrd_stratified is TRUE if there is such a loop.
 
221
     This is done directly in this function, for each subgoal $S$ in
 
222
     the independent SCC, the completion_suspension frames if $S$ are
 
223
     traversed to see whether there is a ptcp (root subgoal) pointer
 
224
     to some subgoal $S'$ in the independet SCC.  If so,
 
225
     non_lrd_stratified is set to true, and the $S$ is marked as
 
226
     delayed.  
 
227
  */
 
228
 
 
229
  if (sccs_needed) {
 
230
    xsbBool found;
 
231
    CPtr nsf;
 
232
    CPtr CopyFrame;
 
233
    ComplStackFrame csf, max_finish_csf;
 
234
    xsbBool non_lrd_stratified;
 
235
 
 
236
#ifdef VERBOSE_COMPLETION
 
237
    xsb_dbgmsg((LOG_DEBUG,"\t===> SCC detection is needed...(%d subgoals in ASCC)...",
 
238
               (int)((leader_compl_frame-openreg)/COMPLFRAMESIZE+1)));
 
239
    print_completion_stack();
 
240
#endif
 
241
 
 
242
    construct_dep_graph(CTXTc (ComplStackFrame)leader_compl_frame);
 
243
    dbg_print_completion_stack(LOG_COMPLETION);
 
244
 
 
245
    max_finish_csf = DFS_DGT(CTXTc (ComplStackFrame)leader_compl_frame);
 
246
    xsb_dbgmsg((LOG_COMPLETION, 
 
247
               "! MAX FINISH_SUBGOAL AT COMPL STACK: %p",max_finish_csf));
 
248
    /* mark as not visited all subgoals in the completion stack
 
249
     * below leader_compl_frame */
 
250
    unvisit((ComplStackFrame)leader_compl_frame);
 
251
 
 
252
    /* mark as visited all subgoals in the same SCC as max_finish_csf 
 
253
     * by traversing the SDG */
 
254
    find_independent_scc(max_finish_csf);
 
255
    
 
256
    dbg_print_completion_stack(LOG_COMPLETION);
 
257
 
 
258
    /* Perform a LRD stratification check of the program-query pair     */
 
259
    /* and classify the completion suspensions as stratified or not.    */
 
260
    ComplStkFrame = leader_compl_frame;
 
261
    non_lrd_stratified = FALSE;
 
262
    
 
263
    while (ComplStkFrame >= openreg) {
 
264
      CPtr    susp_csf;
 
265
      VariantSF susp_subgoal;
 
266
 
 
267
      curr_subg = compl_subgoal_ptr(ComplStkFrame);
 
268
      if (!is_completed(curr_subg)) {
 
269
        if (compl_visited(ComplStkFrame) != FALSE) {
 
270
          curr_subg = compl_subgoal_ptr(ComplStkFrame);  
 
271
          for (nsf = subg_compl_susp_ptr(curr_subg);
 
272
               nsf != NULL; nsf = csf_prevcsf(nsf)) {
 
273
            if ((susp_subgoal = ptcp_of_csusp(nsf)) != NULL) {
 
274
              susp_csf = subg_compl_stack_ptr(susp_subgoal);      
 
275
              if (!is_completed(susp_subgoal) && 
 
276
                  susp_csf <= leader_compl_frame &&
 
277
                  compl_visited(susp_csf) != FALSE) {
 
278
                /*--- The suspended subgoal is in the completable SCC ---*/
 
279
                mark_delayed(ComplStkFrame, susp_csf, nsf);
 
280
                non_lrd_stratified = TRUE;
 
281
                xsb_dbgmsg((LOG_DELAY, "\t   Subgoal "));
 
282
                dbg_print_subgoal(LOG_DELAY,stddbg,(VariantSF)susp_subgoal);
 
283
                xsb_dbgmsg((LOG_DELAY, " depends negatively on subgoal "));
 
284
                dbg_print_subgoal(LOG_DELAY, stddbg, curr_subg);
 
285
                xsb_dbgmsg((LOG_DELAY, "\n"));
 
286
              } /*  no completed susp_subg */
 
287
            }
 
288
          } /* for each nsf */
 
289
        } /* not visited */
 
290
      } /* skip completed subgoals in the completion stack */
 
291
      ComplStkFrame = next_compl_frame(ComplStkFrame);
 
292
    } /* while */
 
293
  
 
294
/* #define SERIOUS_DEBUGGING_NEEDED     */
 
295
#ifdef SERIOUS_DEBUGGING_NEEDED
 
296
    print_completion_stack();
 
297
#endif
 
298
 
 
299
/*----------------------------------------------------------------------*/
 
300
    /* 
 
301
       In the case where there is no loop through negation in the
 
302
       independent SCC (non_lrd_stratified == FALSE, then the SLGWAM
 
303
       needs to find the continuation, the youngest subgoal of the
 
304
       ASCC that will not be completed.  
 
305
 
 
306
       If the independent SCC has a loop through negation, the
 
307
       continuation pointer will be the leader breg, otherwise, it
 
308
       will be the breg of the youngest subgoal not in the independent
 
309
       ASCC (I dont understand this, according to my thinking it might
 
310
       as well be the leader, as we will have to do SCC checks, etc
 
311
       again.
 
312
 
 
313
       One trick that is used is that compl_visited can now be set to
 
314
       DELAYED (-1), FALSE (0) or true (1).  The continuation will be
 
315
       set to the breg of the first subgoal whose compl_visited value
 
316
       is neither FALSE or delayed.  
 
317
 
 
318
       While I have not verified this, my understanding is that
 
319
       starting with openreg, there will be a contiguous segment of
 
320
       compl stack frames that are TRUE, followed by a csf that is
 
321
       either FALSE or DELAYED.  Apparently it should be DELAYED only
 
322
       if the independent SCC contains aloop through negation.
 
323
       Therefore, I dont see why there is a <= FALSE below --
 
324
       according to my theory (which could be wrong) it should ==
 
325
       FALSE, since non_lrd_stratified == FALSE.
 
326
    */
 
327
 
 
328
    if (non_lrd_stratified == FALSE) {
 
329
      found = FALSE;
 
330
      for (ComplStkFrame = openreg;
 
331
           !found && ComplStkFrame <= leader_compl_frame;
 
332
           ComplStkFrame = prev_compl_frame(ComplStkFrame)) {
 
333
        if (compl_visited(ComplStkFrame) <= FALSE) {
 
334
          cont_breg = subg_cp_ptr(compl_subgoal_ptr(ComplStkFrame));
 
335
          breg = cont_breg;
 
336
          xsb_dbgmsg((LOG_COMPLETION,
 
337
                     "------ Setting TBreg to %p...", cont_breg));
 
338
          found = TRUE;
 
339
        }
 
340
      }
 
341
       if (!found) {    /* case in which the ASCC contains only one SCC */
 
342
                        /* and all subgoals will be completed (no delay) */
 
343
        cont_breg = tcp_prevbreg(leader_breg);
 
344
      }
 
345
    } else {    /* the chosen SCC has a loop through negation */
 
346
      for (ComplStkFrame = openreg; ComplStkFrame <= leader_compl_frame;
 
347
           ComplStkFrame = prev_compl_frame(ComplStkFrame)) {
 
348
        if (compl_visited(ComplStkFrame) != FALSE)
 
349
          compl_visited(ComplStkFrame) = DELAYED;
 
350
      }
 
351
      cont_breg = subg_cp_ptr(compl_subgoal_ptr(leader_compl_frame));
 
352
      breg = cont_breg;
 
353
      xsb_dbgmsg((LOG_COMPLETION, "------ Setting TBreg to %p...", cont_breg));
 
354
    }
 
355
    
 
356
/*----------------------------------------------------------------------*/
 
357
    /* 
 
358
       The next loop has two functions.  First, any subgoals that are
 
359
       completely evaluated (those that are visited but not delayed)
 
360
       are marked as completed.  In addition, breg will be set to
 
361
       point to the cP for the the youngest subgoal that has been
 
362
       visited (delayed or not).  The failure continuation of this CP
 
363
       in turn will be the continuation obtained above.  
 
364
 
 
365
       One point to make is that reclaim_incomplete_table_structs()
 
366
       Clears up some table structures for subsumptive tabling, and
 
367
       presumably the answer list for variant tabling.  It also frees
 
368
       consumer choice points in CHAT.  In either case, frozen local
 
369
       stack, heap, (and trail & cp space in the SLGWAM) will only be
 
370
       reclaimed upon completion of the leader.       
 
371
    */
 
372
 
 
373
 {
 
374
   for (ComplStkFrame = leader_compl_frame; ComplStkFrame >= openreg;
 
375
        ComplStkFrame = next_compl_frame(ComplStkFrame)) {
 
376
     if (compl_visited(ComplStkFrame) != FALSE) {
 
377
       curr_subg = compl_subgoal_ptr(ComplStkFrame);
 
378
       if (compl_visited(ComplStkFrame) != DELAYED) {
 
379
#ifdef CONC_COMPL
 
380
      if( !is_completed(curr_subg) )
 
381
      {
 
382
        mark_as_completed(curr_subg);
 
383
        WakeDependentThreads(th, curr_subg);
 
384
      }
 
385
#else
 
386
      mark_as_completed(curr_subg);
 
387
#endif
 
388
         reclaim_incomplete_table_structs(curr_subg);
 
389
         if (neg_simplif_possible(curr_subg)) {
 
390
           simplify_neg_fails(CTXTc curr_subg);
 
391
         }
 
392
       }
 
393
       
 
394
/*----------------------------------------------------------------------*/
 
395
       /* Now, its time to schedule the completion suspensions found
 
396
          for the youngest subgoal in the independent SCC, as found in
 
397
          the previous loop.  
 
398
 
 
399
          There are a couple of anomalies in this procedure, for the
 
400
          SLGWAM.  The first is that we have completion suspension as
 
401
          "single-dispatch", that is only one completion suspension is
 
402
          scheduled for each dependency check --- I thought that we
 
403
          used to dispatch completion_suspension frames for all
 
404
          subgoals in the independent SCC???  Second, there is a
 
405
          completion_suspension CP that is created.
 
406
          Completion_suspension CPs, as opposed to completion
 
407
          suspension frames, are archaic remnants of single-stack
 
408
          scheduling.  I believe their creation here is unnecessary.
 
409
          In principle, we should be able to simply set the breg to
 
410
          the first of the completion_suspension Frames.
 
411
       */
 
412
 
 
413
       if ((nsf = subg_compl_susp_ptr(curr_subg)) != NULL) {
 
414
         CPtr min_breg;
 
415
         
 
416
         set_min(min_breg, breg, bfreg);
 
417
         if (compl_visited(ComplStkFrame) != DELAYED) {
 
418
           save_compl_susp_cp(min_breg, cont_breg, nsf);
 
419
           breg = min_breg;
 
420
           /*-- forget these completion suspensions --*/
 
421
           subg_compl_susp_ptr(curr_subg) = NULL;
 
422
#ifdef VERBOSE_COMPLETION
 
423
           xsb_dbgmsg((LOG_DEBUG,"------ Setting Breg to %p...", breg));
 
424
#endif
 
425
         } else {       /* unsuspend only those suspensions that are delayed */
 
426
           CPtr dnsf = NULL, ndnsf = NULL;
 
427
           CPtr head_dnsf = NULL, head_ndnsf = NULL;
 
428
           while (nsf != NULL) {        /* partition into two lists */
 
429
             if (csf_neg_loop(nsf) == FALSE) {
 
430
               if (ndnsf == NULL) head_ndnsf = nsf; 
 
431
               else csf_prevcsf(ndnsf) = nsf;
 
432
               ndnsf = nsf;
 
433
               nsf = csf_prevcsf(nsf);
 
434
               csf_prevcsf(ndnsf) = NULL;
 
435
             } else {
 
436
               if (dnsf == NULL) head_dnsf = nsf; 
 
437
               else csf_prevcsf(dnsf) = nsf;
 
438
               dnsf = nsf;
 
439
               nsf = csf_prevcsf(nsf);
 
440
               csf_prevcsf(dnsf) = NULL;
 
441
             }
 
442
           }
 
443
           if (head_dnsf != NULL) {
 
444
             save_compl_susp_cp(min_breg, cont_breg, head_dnsf);
 
445
             breg = min_breg;
 
446
           }
 
447
           subg_compl_susp_ptr(curr_subg) = head_ndnsf;
 
448
         }
 
449
         cont_breg = breg; /* So that other Compl_Susp_CPs can be saved. */
 
450
       }
 
451
     }
 
452
   }
 
453
 }
 
454
    xsb_dbgmsg((LOG_COMPLETION, "------ Completed the chosen SCC..."));
 
455
/*----------------------------------------------------------------------*/
 
456
    /* Finally, compact the Completion Stack (and reclaim edge 
 
457
       space for the dependency graphs).
 
458
       
 
459
       Might be useful to only copy the frame if CopyFrame is not
 
460
       == the ComplStkFrame
 
461
    */
 
462
 
 
463
    ComplStkFrame = CopyFrame = leader_compl_frame; 
 
464
    while (ComplStkFrame >= openreg) {
 
465
      curr_subg = compl_subgoal_ptr(ComplStkFrame);
 
466
      reclaim_edge_space((ComplStackFrame)ComplStkFrame);
 
467
      if (!is_completed(curr_subg)) {
 
468
        subg_compl_stack_ptr(curr_subg) = CopyFrame;
 
469
        /* the macro below also updates CopyFrame */
 
470
        compact_completion_frame(CopyFrame, ComplStkFrame, curr_subg);
 
471
      } else { /* this may be done 2x! */
 
472
        reclaim_incomplete_table_structs(curr_subg);
 
473
      }
 
474
      ComplStkFrame = next_compl_frame(ComplStkFrame);
 
475
    }
 
476
    openreg = prev_compl_frame(CopyFrame);
 
477
 
 
478
/*----------------------------------------------------------------------*/
 
479
 
 
480
    /* 
 
481
       This next loop chains some of the TCPs, but does not form what
 
482
       I would think of as a scheduling chain -- it simply removes any
 
483
       pointers to completed subgoals whose space has been reclaimed.
 
484
 
 
485
       The line
 
486
 
 
487
    tcp_prevbreg(subg_cp_ptr(compl_subgoal_ptr(leader_compl_frame))) = 
 
488
      tcp_prevbreg(subg_cp_ptr(leader_subg));
 
489
 
 
490
      looks anomalous at first, but the leader compl_frame may have
 
491
      been compacted away, thus its continuation must be preserved for
 
492
      whoever is the new leader.
 
493
 
 
494
      However, I dont believe that the "for" loop is necessary, as it
 
495
      doesn't matter what the tcp_breg is for choice points that are
 
496
      not leaders (and if they are promoted to leaders, their
 
497
      tcp_prevbreg value will be adjusted anyway.
 
498
     */
 
499
 
 
500
    tcp_prevbreg(subg_cp_ptr(compl_subgoal_ptr(leader_compl_frame))) = 
 
501
      tcp_prevbreg(subg_cp_ptr(leader_subg));
 
502
    for (ComplStkFrame = next_compl_frame(leader_compl_frame);
 
503
         ComplStkFrame >= openreg;
 
504
         ComplStkFrame = next_compl_frame(ComplStkFrame)){
 
505
      tcp_prevbreg(subg_cp_ptr(compl_subgoal_ptr(ComplStkFrame))) = 
 
506
        subg_cp_ptr(compl_subgoal_ptr(prev_compl_frame(ComplStkFrame)));
 
507
    }
 
508
  } /* if sccs_needed */
 
509
  else { /* sccs not needed */
 
510
    ComplStkFrame = leader_compl_frame;
 
511
    while (ComplStkFrame >= openreg) {
 
512
      curr_subg = compl_subgoal_ptr(ComplStkFrame);
 
513
#ifdef CONC_COMPL
 
514
      if( !is_completed(curr_subg) )
 
515
      {
 
516
        mark_as_completed(curr_subg);
 
517
        WakeDependentThreads(th, curr_subg);
 
518
      }
 
519
#else
 
520
      mark_as_completed(curr_subg);
 
521
#endif
 
522
      if (neg_simplif_possible(curr_subg)) {
 
523
        simplify_neg_fails(CTXTc curr_subg);
 
524
      }
 
525
      ComplStkFrame = next_compl_frame(ComplStkFrame);
 
526
    }
 
527
    
 
528
    ComplStkFrame = leader_compl_frame;
 
529
    while (ComplStkFrame >= openreg) {
 
530
      curr_subg = compl_subgoal_ptr(ComplStkFrame);
 
531
      reclaim_incomplete_table_structs(curr_subg);
 
532
      ComplStkFrame = next_compl_frame(ComplStkFrame);
 
533
    }
 
534
    /* point openreg to first empty space */
 
535
    openreg = prev_compl_frame(leader_compl_frame);     
 
536
  }
 
537
  
 
538
  xsb_dbgmsg((LOG_COMPLETION, "------ Completed an ASCC..."));
 
539
} /* compute_wfs() */
 
540
 
 
541
/*----------------------------------------------------------------------*/