/* File: gc_copy.h
** Author(s): Luis Castro, Bart Demoen, Kostis Sagonas
** Contact: xsb-contact@cs.sunysb.edu
**
** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
** Copyright (C) ECRC, Germany, 1990
**
** XSB is free software; you can redistribute it and/or modify it under the
** terms of the GNU Library General Public License as published by the Free
** Software Foundation; either version 2 of the License, or (at your option)
** any later version.
**
** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for
** more details.
**
** You should have received a copy of the GNU Library General Public License
** along with XSB; if not, write to the Free Software Foundation,
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** $Id: gc_copy.h,v 1.5 2002/05/31 15:09:02 lfcastro Exp $
**
*/
/*=======================================================================*/
/* Heap collection by copying */
/* Marking is finished and new heap allocated */
/* Idea is to copy a la Cheney and copy immediatly back to original */
/* heap - this allows release of the new heap */
/* Cheney is slightly adapted to make it possible to have */
/* the copy back as a mem copy; so heap pointers during Cheney */
/* will already point to the final destination */
/* */
/* It is very similar to the BinProlog garbage collector. */
/*=======================================================================*/
#ifdef GC
/* the following variables are set by copy_heap() and used as */
/* globals in the two functions below. */
static int offset;
static CPtr scan, next;
#ifdef DEBUG_ASSERTIONS
static void CHECK(CPtr p)
{ CPtr q;
q = (CPtr)(*p);
if (((heap_bot - offset) <= q) && (q < next)) return;
xsb_dbgmsg((LOG_GC, "really bad thing discovered"));
} /* CHECK */
#define GCDBG(mes,val) /*if (num_gc == 61)*/ xsb_dbgmsg((LOG_GC,mes,val))
#else
#define CHECK(p)
#define GCDBG(mes,val)
#endif
#define adapt_external_heap_pointer(P,Q,TAG) \
CHECK(Q);\
GCDBG("Adapting %p ", P); GCDBG("with %p ", Q);\
Q = (CPtr)((CPtr)(cell(Q))+offset); \
if (TAG == XSB_REF || TAG == XSB_REF1) {\
bld_ref(P, Q); \
} else {\
cell(P) = (Cell)(enc_addr(Q) | TAG); \
} \
GCDBG("to %lx\n", cell(P))
#define copy_block(HP,NEXT) /* make sure this macro does not modify HP ! */\
i = HP-heap_bot; \
while (h_marked(--i)) ; /* assumes that h_marked[-1] = 0 !!! */\
/* while (--i >= 0 && h_marked(i)) ; otherwise */\
p = heap_bot+i+1;\
for (i = p-heap_bot; h_marked(i); p++, i++) { \
h_clear_mark(i); \
cell(NEXT) = cell(p); \
cell(p) = (Cell)(NEXT); /* leave a forwarding pointer */\
NEXT++; \
}
static void find_and_copy_block(CPtr hp)
{
int i, tag;
CPtr p, q, addr;
/* copy the block into the new heap area */
copy_block(hp,next);
/* perform a Cheney scan: pointer "scan" chases the "next" pointer */
/* note that "next" is modified inside the for loop by copy_block() */
for ( ; scan < next; scan++) {
q = (CPtr)cell(scan);
tag = cell_tag(q);
switch (tag) {
case XSB_REF:
case XSB_REF1:
if (points_into_heap(q)) {
GCDBG("Reference to heap with tag %d\n", tag);
xsb_dbgmsg((LOG_GC, "In adapting case for %p with %p (%lx)...",
scan, q, cell(q)));
if (h_marked(q-heap_bot)) {
copy_block(q,next);
}
q = (CPtr)((CPtr)(cell(q))+offset);
GCDBG(" to be adapted to %p\n", q);
bld_ref(scan, q);
}
break;
case XSB_STRUCT :
addr = (CPtr)cs_val(q);
GCDBG("Structure pointing to %p found...\n", addr);
if (h_marked(addr-heap_bot)) { /* if structure not already copied */
copy_block(addr,next); /* this modifies *addr */
}
CHECK(addr);
GCDBG("*p = %lx ", cell(addr));
addr = (CPtr)((CPtr)(cell(addr))+offset);
GCDBG("q = %p ", addr);
bld_cs(scan, addr);
GCDBG("made to point to %lx\n", cell(scan));
break;
case XSB_LIST :
addr = clref_val(q);
GCDBG("List %p found... \n", addr);
if (h_marked(addr-heap_bot)) { /* if list head not already copied */
copy_block(addr,next); /* this modifies *addr */
}
CHECK(addr);
addr = (CPtr)((CPtr)(cell(addr))+offset);
bld_list(scan, addr);
break;
case XSB_ATTV:
addr = clref_val(q);
GCDBG("Attv %p found... \n", addr);
if (h_marked(addr-heap_bot)) {
copy_block(addr,next);
}
CHECK(addr);
addr = (CPtr)((CPtr)(cell(addr))+offset);
bld_attv(scan, addr);
break;
default :
break;
}
}
} /* find_and_copy_block */
#endif /* GC */
/*-------------------------------------------------------------------------*/
#ifdef GC
inline static void adapt_hreg_from_choicepoints(CPtr h)
{
CPtr b, bprev;
/* only after copying collection */
b = breg;
b = top_of_cpstack;
bprev = 0;
while (b != bprev) {
cp_hreg(b) = h;
bprev = b;
b = cp_prevbreg(b);
}
} /* adapt_hreg_from_choicepoints */
#endif
#ifdef SLG_GC
inline static void adapt_hfreg_from_choicepoints(CPtr h)
{
CPtr b, bprev;
b = (bfreg < breg ? bfreg : breg);
bprev = 0;
while (1) {
if (is_generator_choicepoint(b))
tcp_hfreg(b) = h;
cp_hreg(b) = h;
b = cp_prevtop(b);
if (b >= (cp_bot - CP_SIZE))
break;
}
}
#endif
/*=======================================================================*/
#ifdef GC
static CPtr copy_heap(int marked, CPtr begin_new_h, CPtr end_new_h, int arity)
{
CPtr p, q;
int tag;
Cell contents;
offset = heap_bot-begin_new_h;
scan = next = begin_new_h;
xsb_dbgmsg((LOG_GC,
"New heap space between %p and %p", begin_new_h,end_new_h));
/* the order in which stuff is copied might be important */
/* but like the price of a ticket from Seattle to New York: nobody knows */
/* trail */
/* more precise traversal of trail possible */
{ CPtr endtr ;
endtr = tr_top ;
for (p = tr_bot; p <= endtr; p++) {
contents = cell(p);
#ifdef SLG_GC
if (!tr_marked(p-tr_bot))
continue;
tr_clear_mark(p-tr_bot);
#endif
q = hp_pointer_from_cell(contents,&tag) ;
if (!q) continue ;
if (h_marked(q-heap_bot))
find_and_copy_block(q);
adapt_external_heap_pointer(p,q,tag);
}
#ifdef PRE_IMAGE_TRAIL
/* re-tag pre image cells in trail */
if (tr_pre_marked(p-tr_bot)) {
*p = *p | PRE_IMAGE_MARK;
tr_clear_pre_mark(p-tr_bot);
}
#endif
}
/* choicepoints */
/* a more precise traversal of choicepoints is possible */
{ CPtr endcp ;
endcp = cp_top ;
for (p = cp_bot; p >= endcp ; p--)
{ contents = cell(p) ;
q = hp_pointer_from_cell(contents,&tag) ;
if (!q) continue ;
if (h_marked(q-heap_bot)) { find_and_copy_block(q); }
adapt_external_heap_pointer(p,q,tag);
}
}
/* local stack */
/* a more precise traversal of local stack is possible */
{ CPtr endls;
endls = ls_top ;
for (p = ls_bot; p >= endls ; p-- )
{ if (! ls_marked(p-ls_top)) continue ;
ls_clear_mark((p-ls_top)) ;
contents = cell(p) ;
q = hp_pointer_from_cell(contents,&tag) ;
if (!q) continue ;
if (h_marked(q-heap_bot)) { find_and_copy_block(q); }
adapt_external_heap_pointer(p,q,tag);
}
}
/* now do the argument registers */
{ CPtr p;
for (p = reg+1; arity-- > 0; p++)
{ contents = cell(p) ;
q = hp_pointer_from_cell(contents,&tag) ;
if (!q) continue ;
if (h_marked(q-heap_bot)) { find_and_copy_block(q); }
adapt_external_heap_pointer(p,q,tag);
}
}
/* now do the delay register */
{ CPtr p;
if (delayreg != NULL)
{
p = (CPtr)(&delayreg);
contents = cell(p) ;
q = hp_pointer_from_cell(contents,&tag) ;
if (!q)
xsb_dbgmsg((LOG_GC, "non null delayreg points not in heap"));
else
{
if (h_marked(q-heap_bot)) { find_and_copy_block(q); }
adapt_external_heap_pointer(p,q,tag);
}
}
}
if (next != end_new_h) {
xsb_dbgmsg((LOG_GC, "heap copy gc - inconsistent hreg: %d cells not copied. (num_gc=%d)\n",
(end_new_h-next),num_gc));
}
memcpy((void *)heap_bot, (void *)begin_new_h, marked*sizeof(Cell));
return(heap_bot+marked);
} /* copy_heap */
#endif /* GC */
syntax highlighted by Code2HTML, v. 0.9.1