2001-04-09 20:54:03 +01:00
/*************************************************************************
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L . Damas , V . S . Costa and Universidade do Porto 1985 - 1997 *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* File : heapgc . c *
* Last rev : *
* mods : *
* comments : Global Stack garbage collector *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef SCCS
static char SccsId [ ] = " %W% %G% " ;
# endif /* SCCS */
# include "absmi.h"
# include "yapio.h"
2004-02-05 16:57:02 +00:00
# include "alloc.h"
2005-02-18 21:34:02 +00:00
# include "attvar.h"
2001-04-09 20:54:03 +01:00
2002-05-07 22:19:52 +01:00
2001-04-18 13:24:45 +01:00
# define EARLY_RESET 1
2002-02-18 15:26:41 +00:00
# if !defined(TABLING)
2001-12-20 01:07:42 +00:00
# define EASY_SHUNTING 1
2005-07-06 20:34:12 +01:00
# endif /* !TABLING */
2001-05-22 13:37:23 +01:00
# define HYBRID_SCHEME 1
2001-05-21 21:00:05 +01:00
2001-04-09 20:54:03 +01:00
/* global variables for garbage collection */
/* in a single gc */
2005-09-21 04:49:33 +01:00
static unsigned long int total_marked , total_oldies ; /* number of heap objects marked */
2001-04-09 20:54:03 +01:00
2004-11-04 18:22:36 +00:00
# if DEBUG
2003-09-25 00:53:48 +01:00
# ifdef COROUTINING
static unsigned long int total_smarked ;
# endif
2004-11-04 18:22:36 +00:00
# endif
2003-09-25 00:53:48 +01:00
2001-04-09 20:54:03 +01:00
STATIC_PROTO ( Int p_inform_gc , ( void ) ) ;
STATIC_PROTO ( Int p_gc , ( void ) ) ;
2001-05-02 15:19:10 +01:00
# ifdef EASY_SHUNTING
2001-04-09 20:54:03 +01:00
static choiceptr current_B ;
2001-04-26 15:44:43 +01:00
2001-12-02 16:54:39 +00:00
static tr_fr_ptr sTR , sTR0 ;
2001-06-06 20:10:51 +01:00
static CELL * prev_HB ;
2001-04-09 20:54:03 +01:00
# endif
2001-05-21 21:00:05 +01:00
static tr_fr_ptr new_TR ;
2005-09-21 04:49:33 +01:00
static CELL * HGEN ;
2001-04-09 20:54:03 +01:00
STATIC_PROTO ( void push_registers , ( Int , yamop * ) ) ;
STATIC_PROTO ( void marking_phase , ( tr_fr_ptr , CELL * , yamop * , CELL * ) ) ;
STATIC_PROTO ( void compaction_phase , ( tr_fr_ptr , CELL * , yamop * , CELL * ) ) ;
STATIC_PROTO ( void pop_registers , ( Int , yamop * ) ) ;
STATIC_PROTO ( void init_dbtable , ( tr_fr_ptr ) ) ;
STATIC_PROTO ( void mark_db_fixed , ( CELL * ) ) ;
STATIC_PROTO ( void mark_regs , ( tr_fr_ptr ) ) ;
STATIC_PROTO ( void mark_trail , ( tr_fr_ptr , tr_fr_ptr , CELL * , choiceptr ) ) ;
STATIC_PROTO ( void mark_environments , ( CELL * , OPREG , CELL * ) ) ;
2002-01-28 04:30:40 +00:00
STATIC_PROTO ( void mark_choicepoints , ( choiceptr , tr_fr_ptr , int ) ) ;
2001-04-09 20:54:03 +01:00
STATIC_PROTO ( void into_relocation_chain , ( CELL * , CELL * ) ) ;
STATIC_PROTO ( void sweep_trail , ( choiceptr , tr_fr_ptr ) ) ;
STATIC_PROTO ( void sweep_environments , ( CELL * , OPREG , CELL * ) ) ;
STATIC_PROTO ( void sweep_choicepoints , ( choiceptr ) ) ;
STATIC_PROTO ( choiceptr update_B_H , ( choiceptr , CELL * , CELL * , CELL * ) ) ;
STATIC_PROTO ( void compact_heap , ( void ) ) ;
STATIC_PROTO ( void update_relocation_chain , ( CELL * , CELL * ) ) ;
2002-11-11 17:38:10 +00:00
STATIC_PROTO ( int is_gc_verbose , ( void ) ) ;
2002-01-28 04:30:40 +00:00
STATIC_PROTO ( int is_gc_very_verbose , ( void ) ) ;
2001-04-09 20:54:03 +01:00
# include "heapgc.h"
2004-09-16 18:29:08 +01:00
# if GC_NO_TAGS
char * bp ;
# endif
2001-04-09 20:54:03 +01:00
static int discard_trail_entries = 0 ;
2001-05-02 15:19:10 +01:00
/* support for hybrid garbage collection scheme */
2001-06-27 13:46:35 +01:00
typedef struct {
CELL * v ;
int nof ;
} cont ;
2001-12-02 16:54:39 +00:00
# ifdef EASY_SHUNTING
# define cont_top0 (cont *)sTR
# else
static cont * cont_top0 ;
# endif
static cont * cont_top ;
2001-06-27 13:46:35 +01:00
2004-10-28 21:12:23 +01:00
static void
2004-10-27 16:56:34 +01:00
gc_growtrail ( int committed )
{
# if USE_SYSTEM_MALLOC
2005-01-04 02:50:23 +00:00
TR = OldTR ;
2004-10-27 16:56:34 +01:00
# endif
2004-12-28 22:20:37 +00:00
if ( ! Yap_growtrail ( 64 * 1024L , TRUE ) ) {
2004-10-27 16:56:34 +01:00
/* could not find more trail */
longjmp ( Yap_gc_restore , 2 ) ;
}
# if USE_SYSTEM_MALLOC
# if !GC_NO_TAGS
if ( committed ) {
longjmp ( Yap_gc_restore , 2 ) ;
}
# endif
longjmp ( Yap_gc_restore , 1 ) ;
# endif
2004-10-28 21:12:23 +01:00
2004-10-27 16:56:34 +01:00
}
2001-06-27 13:46:35 +01:00
inline static void
PUSH_CONTINUATION ( CELL * v , int nof ) {
cont * x ;
if ( nof = = 0 ) return ;
x = cont_top ;
x + + ;
2004-10-27 16:56:34 +01:00
if ( ( ADDR ) x > Yap_TrailTop - 1024 ) {
gc_growtrail ( TRUE ) ;
}
2001-06-27 13:46:35 +01:00
x - > v = v ;
x - > nof = nof ;
cont_top = x ;
}
# define POP_CONTINUATION() { \
if ( cont_top = = cont_top0 ) \
return ; \
else { \
int nof = cont_top - > nof ; \
cont * x = cont_top ; \
\
current = x - > v ; \
if ( nof = = 1 ) \
cont_top = - - x ; \
else { \
x - > nof = nof - 1 ; \
x - > v = current + 1 ; \
} \
} \
goto begin ; }
2001-05-02 15:19:10 +01:00
# ifdef HYBRID_SCHEME
static CELL_PTR * iptop ;
inline static void
PUSH_POINTER ( CELL * v ) {
if ( iptop > = ( CELL_PTR * ) ASP ) return ;
* iptop + + = v ;
}
inline static void
POP_POINTER ( void ) {
if ( iptop > = ( CELL_PTR * ) ASP ) return ;
- - iptop ;
}
inline static void
POPSWAP_POINTER ( CELL_PTR * vp ) {
if ( iptop > = ( CELL_PTR * ) ASP ) return ;
- - iptop ;
if ( vp ! = iptop )
* vp = * iptop ;
}
/*
original code from In Hyuk Choi ,
found at http : //userpages.umbc.edu/~ichoi1/project/cs441.htm
*/
static inline void
2002-01-02 22:26:37 +00:00
exchange ( CELL_PTR * b , Int i , Int j )
2001-05-02 15:19:10 +01:00
{
CELL * t = b [ j ] ;
b [ j ] = b [ i ] ;
b [ i ] = t ;
}
static UInt
2002-01-02 22:26:37 +00:00
partition ( CELL * a [ ] , Int p , Int r )
2001-05-02 15:19:10 +01:00
{
CELL * x ;
UInt i , j ;
x = a [ p ] ;
i = p + 1 ;
j = r ;
2002-01-02 22:26:37 +00:00
while ( a [ j ] > x & & i < j ) {
2001-05-02 15:19:10 +01:00
j - - ;
}
while ( a [ i ] < x & & i < j ) {
i + + ;
}
while ( i < j ) {
exchange ( a , i , j ) ;
i + + ;
j - - ;
2002-01-02 22:26:37 +00:00
while ( a [ j ] > x & & i < j ) {
2001-05-02 15:19:10 +01:00
j - - ;
}
while ( a [ i ] < x & & i < j ) {
i + + ;
}
}
if ( a [ i ] > x )
i - - ;
exchange ( a , p , i ) ;
return ( i ) ;
}
static void
2002-01-02 22:26:37 +00:00
insort ( CELL * a [ ] , Int p , Int q )
2001-05-02 15:19:10 +01:00
{
2002-02-04 16:12:54 +00:00
Int j ;
2001-05-02 15:19:10 +01:00
for ( j = p + 1 ; j < = q ; j + + ) {
CELL * key ;
2002-02-04 16:12:54 +00:00
Int i ;
2001-05-02 15:19:10 +01:00
key = a [ j ] ;
i = j ;
2005-09-21 04:49:33 +01:00
2001-05-02 15:19:10 +01:00
while ( i > p & & a [ i - 1 ] > key ) {
a [ i ] = a [ i - 1 ] ;
i - - ;
}
a [ i ] = key ;
}
}
static void
2002-01-02 22:26:37 +00:00
quicksort ( CELL * a [ ] , Int p , Int r )
2001-05-02 15:19:10 +01:00
{
2002-02-04 16:12:54 +00:00
Int q ;
2001-05-02 15:19:10 +01:00
if ( p < r ) {
if ( r - p < 100 ) {
insort ( a , p , r ) ;
return ;
}
2001-05-02 18:57:42 +01:00
exchange ( a , p , ( p + r ) / 2 ) ;
q = partition ( a , p , r ) ;
quicksort ( a , p , q - 1 ) ;
quicksort ( a , q + 1 , r ) ;
2001-05-02 15:19:10 +01:00
}
}
# else
# define PUSH_POINTER(P)
# define POP_POINTER()
# define POPSWAP_POINTER(P)
# endif /* HYBRID_SCHEME */
2001-04-09 20:54:03 +01:00
2001-07-04 17:48:54 +01:00
# ifdef MULTI_ASSIGNMENT_VARIABLES
/*
Based in opt . mavar . h . This is a set of routines to find out if a
ma trail entry has appeared before in the same trail segment . All ma
entries for the same cell are then linked . At the end of mark_trail ( ) only
one will remain .
*/
# define GC_MAVARS_HASH_SIZE 512
2004-04-16 21:38:54 +01:00
typedef struct gc_ma_hash_entry_struct {
2001-07-04 17:48:54 +01:00
UInt timestmp ;
2004-04-16 21:38:54 +01:00
CELL * addr ;
struct gc_ma_hash_entry_struct * next ;
2001-07-04 17:48:54 +01:00
} gc_ma_hash_entry ;
static gc_ma_hash_entry gc_ma_hash_table [ GC_MAVARS_HASH_SIZE ] ;
2005-08-05 15:55:03 +01:00
static UInt gc_timestamp ; /* an unsigned int */
2001-07-04 17:48:54 +01:00
static inline unsigned int
GC_MAVAR_HASH ( CELL * addr ) {
# if SIZEOF_INT_P==8
return ( ( ( ( unsigned int ) ( ( CELL ) ( addr ) ) ) > > 3 ) % GC_MAVARS_HASH_SIZE ) ;
# else
return ( ( ( ( unsigned int ) ( ( CELL ) ( addr ) ) ) > > 2 ) % GC_MAVARS_HASH_SIZE ) ;
# endif
}
2004-04-16 21:38:54 +01:00
gc_ma_hash_entry * gc_ma_h_top ;
2001-07-04 17:48:54 +01:00
2004-04-16 21:38:54 +01:00
static inline gc_ma_hash_entry *
2001-07-04 17:48:54 +01:00
GC_ALLOC_NEW_MASPACE ( void )
{
2004-04-16 21:38:54 +01:00
gc_ma_hash_entry * new = gc_ma_h_top ;
2002-11-18 18:18:05 +00:00
if ( ( char * ) gc_ma_h_top > Yap_TrailTop - 1024 )
2004-10-27 16:56:34 +01:00
gc_growtrail ( FALSE ) ;
2001-07-04 17:48:54 +01:00
gc_ma_h_top + + ;
2002-02-18 15:26:41 +00:00
cont_top = ( cont * ) gc_ma_h_top ;
2002-02-28 18:25:55 +00:00
# ifdef EASY_SHUNTING
2002-02-18 15:26:41 +00:00
sTR = ( tr_fr_ptr ) cont_top ;
2002-02-28 18:25:55 +00:00
# else
cont_top0 = cont_top ;
# endif
2004-04-16 21:38:54 +01:00
return new ;
2001-07-04 17:48:54 +01:00
}
2004-04-16 21:38:54 +01:00
static inline gc_ma_hash_entry *
2001-07-04 17:48:54 +01:00
gc_lookup_ma_var ( CELL * addr , tr_fr_ptr trp ) {
unsigned int i = GC_MAVAR_HASH ( addr ) ;
2004-04-16 21:38:54 +01:00
gc_ma_hash_entry * nptr , * optr = NULL ;
2001-07-04 17:48:54 +01:00
2005-08-05 15:55:03 +01:00
if ( gc_ma_hash_table [ i ] . timestmp ! = gc_timestamp ) {
gc_ma_hash_table [ i ] . timestmp = gc_timestamp ;
2004-04-16 21:38:54 +01:00
gc_ma_hash_table [ i ] . addr = addr ;
gc_ma_hash_table [ i ] . next = NULL ;
return NULL ;
2001-07-04 17:48:54 +01:00
}
2004-04-16 21:38:54 +01:00
nptr = gc_ma_hash_table + i ;
while ( nptr ) {
optr = nptr ;
2001-07-04 17:48:54 +01:00
if ( nptr - > addr = = addr ) {
2004-04-16 21:38:54 +01:00
return nptr ;
2001-07-04 17:48:54 +01:00
}
nptr = nptr - > next ;
}
nptr = GC_ALLOC_NEW_MASPACE ( ) ;
optr - > next = nptr ;
nptr - > addr = addr ;
nptr - > next = NULL ;
2004-04-16 21:38:54 +01:00
return NULL ;
2001-07-04 17:48:54 +01:00
}
static inline void
2004-04-16 21:38:54 +01:00
GC_NEW_MAHASH ( gc_ma_hash_entry * top ) {
2005-08-05 15:55:03 +01:00
UInt time = + + gc_timestamp ;
2001-07-04 17:48:54 +01:00
if ( time = = 0 ) {
unsigned int i ;
2005-05-26 18:50:06 +01:00
2001-07-04 17:48:54 +01:00
/* damn, we overflowed */
for ( i = 0 ; i < GC_MAVARS_HASH_SIZE ; i + + )
2005-05-26 18:50:06 +01:00
gc_ma_hash_table [ i ] . timestmp = 0L ;
2005-08-05 15:55:03 +01:00
time = + + gc_timestamp ;
2001-07-04 17:48:54 +01:00
}
gc_ma_h_top = top ;
2002-02-18 15:26:41 +00:00
cont_top = ( cont * ) gc_ma_h_top ;
2002-02-28 18:25:55 +00:00
# ifdef EASY_SHUNTING
2002-02-18 15:26:41 +00:00
sTR = ( tr_fr_ptr ) cont_top ;
2002-02-28 18:25:55 +00:00
# else
cont_top0 = cont_top ;
# endif
2001-07-04 17:48:54 +01:00
}
# endif
2001-04-09 20:54:03 +01:00
/* find all accessible objects on the heap and squeeze out all the rest */
/* push the active registers onto the trail for inclusion during gc */
static void
push_registers ( Int num_regs , yamop * nextop )
{
int i ;
2005-10-28 18:38:50 +01:00
StaticArrayEntry * sal = StaticArrays ;
2001-04-09 20:54:03 +01:00
2002-05-23 04:52:34 +01:00
/* push array entries first */
2005-10-28 18:38:50 +01:00
ArrayEntry * al = DynamicArrays ;
while ( al ) {
TrailTerm ( TR + + ) = al - > ValueOfVE ;
al = al - > NextAE ;
}
while ( sal ) {
if ( sal - > ArrayType = = array_of_nb_terms ) {
UInt arity = - sal - > ArrayEArity , i ;
for ( i = 0 ; i < arity ; i + + ) {
Term tlive = sal - > ValueOfVE . lterms [ i ] . tlive ;
if ( ! IsVarTerm ( tlive ) | | ! IsUnboundVar ( & sal - > ValueOfVE . lterms [ i ] . tlive ) ) {
TrailTerm ( TR + + ) = tlive ;
}
}
2002-05-23 04:52:34 +01:00
}
2005-10-28 18:38:50 +01:00
sal = sal - > NextAE ;
2002-05-23 04:52:34 +01:00
}
2005-09-21 04:49:33 +01:00
TrailTerm ( TR ) = GcGeneration ;
TR + + ;
2001-04-09 20:54:03 +01:00
# ifdef COROUTINING
TrailTerm ( TR ) = WokenGoals ;
TrailTerm ( TR + 1 ) = MutableList ;
TrailTerm ( TR + 2 ) = AttsMutableList ;
TrailTerm ( TR + 3 ) = DelayedVars ;
TR + = 4 ;
# endif
for ( i = 1 ; i < = num_regs ; i + + )
TrailTerm ( TR + + ) = ( CELL ) XREGS [ i ] ;
/* push any live registers we might have hanging around */
2002-11-18 18:18:05 +00:00
if ( nextop - > opc = = Yap_opcode ( _move_back ) | |
nextop - > opc = = Yap_opcode ( _skip ) ) {
2001-04-09 20:54:03 +01:00
CELL * lab = ( CELL * ) ( nextop - > u . l . l ) ;
CELL max = lab [ 0 ] ;
Int curr = lab [ 1 ] ;
lab + = 2 ;
if ( max ) {
CELL i ;
for ( i = 0L ; i < = max ; i + + ) {
if ( i = = 8 * CellSize ) {
curr = lab [ 0 ] ;
lab + + ;
}
if ( curr & 1 ) {
TrailTerm ( TR + + ) = XREGS [ i ] ;
}
curr > > = 1 ;
}
}
}
}
/* pop the corrected register values from the trail and update the registers */
static void
pop_registers ( Int num_regs , yamop * nextop )
{
int i ;
tr_fr_ptr ptr = TR ;
2005-10-28 18:38:50 +01:00
StaticArrayEntry * sal = StaticArrays ;
2001-04-09 20:54:03 +01:00
2002-05-23 04:52:34 +01:00
/* pop array entries first */
2005-10-28 18:38:50 +01:00
ArrayEntry * al = DynamicArrays ;
while ( al ) {
al - > ValueOfVE = TrailTerm ( ptr + + ) ;
al = al - > NextAE ;
}
sal = StaticArrays ;
while ( sal ) {
if ( sal - > ArrayType = = array_of_nb_terms ) {
UInt arity = - sal - > ArrayEArity ;
for ( i = 0 ; i < arity ; i + + ) {
Term tlive = sal - > ValueOfVE . lterms [ i ] . tlive ;
if ( ! IsVarTerm ( tlive ) | | ! IsUnboundVar ( & sal - > ValueOfVE . lterms [ i ] . tlive ) ) {
sal - > ValueOfVE . lterms [ i ] . tlive = TrailTerm ( ptr + + ) ;
}
}
2002-05-23 04:52:34 +01:00
}
2005-10-28 18:38:50 +01:00
sal = sal - > NextAE ;
2002-05-23 04:52:34 +01:00
}
2005-09-21 04:49:33 +01:00
GcGeneration = TrailTerm ( ptr + + ) ;
2001-04-09 20:54:03 +01:00
# ifdef COROUTINING
# ifdef MULTI_ASSIGNMENT_VARIABLES
WokenGoals = TrailTerm ( ptr + + ) ;
MutableList = TrailTerm ( ptr + + ) ;
AttsMutableList = TrailTerm ( ptr + + ) ;
DelayedVars = TrailTerm ( ptr + + ) ;
# endif
# endif
for ( i = 1 ; i < = num_regs ; i + + )
XREGS [ i ] = TrailTerm ( ptr + + ) ;
/* pop any live registers we might have hanging around */
2002-11-18 18:18:05 +00:00
if ( nextop - > opc = = Yap_opcode ( _move_back ) | |
nextop - > opc = = Yap_opcode ( _skip ) ) {
2001-04-09 20:54:03 +01:00
CELL * lab = ( CELL * ) ( nextop - > u . l . l ) ;
CELL max = lab [ 0 ] ;
Int curr = lab [ 1 ] ;
lab + = 2 ;
if ( max ) {
CELL i ;
for ( i = 0L ; i < = max ; i + + ) {
if ( i = = 8 * CellSize ) {
curr = lab [ 0 ] ;
lab + + ;
}
if ( curr & 1 ) {
XREGS [ i ] = TrailTerm ( ptr + + ) ;
}
curr > > = 1 ;
}
}
}
}
2004-11-04 18:22:36 +00:00
# if DEBUG && COUNT_CELLS_MARKED
2001-04-09 20:54:03 +01:00
static int
count_cells_marked ( void )
{
CELL * current ;
int found_marked = 0 ;
for ( current = H - 1 ; current > = H0 ; current - - ) {
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( current ) ) {
2001-04-09 20:54:03 +01:00
found_marked + + ;
}
}
return ( found_marked ) ;
}
# endif
/* straightforward binary tree scheme that, given a key, finds a
matching dbref */
2003-04-30 18:46:05 +01:00
typedef enum {
db_entry ,
cl_entry ,
lcl_entry ,
2003-10-19 01:33:10 +01:00
li_entry ,
2003-04-30 18:46:05 +01:00
dcl_entry
} db_entry_type ;
2001-04-09 20:54:03 +01:00
typedef struct db_entry {
2003-04-30 18:46:05 +01:00
CODEADDR val ;
db_entry_type db_type ;
2001-04-09 20:54:03 +01:00
struct db_entry * left ;
2003-04-30 18:46:05 +01:00
CODEADDR lim ;
2001-04-09 20:54:03 +01:00
struct db_entry * right ;
} * dbentry ;
2004-09-16 18:29:08 +01:00
static ADDR db_vec , db_vec0 ;
typedef struct RB_red_blk_node {
CODEADDR key ;
CODEADDR lim ;
db_entry_type db_type ;
int red ; /* if red=0 then the node is black */
struct RB_red_blk_node * left ;
struct RB_red_blk_node * right ;
struct RB_red_blk_node * parent ;
} rb_red_blk_node ;
2001-04-09 20:54:03 +01:00
2004-09-16 18:29:08 +01:00
static rb_red_blk_node * db_root , * db_nil ;
2001-04-09 20:54:03 +01:00
2004-09-16 18:29:08 +01:00
static rb_red_blk_node *
RBMalloc ( UInt size )
2001-04-09 20:54:03 +01:00
{
2004-09-16 18:29:08 +01:00
ADDR new = db_vec ;
2001-04-09 20:54:03 +01:00
2004-09-16 18:29:08 +01:00
db_vec + = size ;
2004-10-27 16:56:34 +01:00
if ( ( ADDR ) db_vec > Yap_TrailTop - 1024 ) {
gc_growtrail ( FALSE ) ;
2001-04-09 20:54:03 +01:00
}
2004-09-16 18:29:08 +01:00
return ( rb_red_blk_node * ) new ;
}
static rb_red_blk_node *
RBTreeCreate ( void ) {
rb_red_blk_node * temp ;
/* see the comment in the rb_red_blk_tree structure in red_black_tree.h */
/* for information on nil and root */
temp = db_nil = RBMalloc ( sizeof ( rb_red_blk_node ) ) ;
temp - > parent = temp - > left = temp - > right = temp ;
temp - > red = 0 ;
temp - > key = NULL ;
temp = RBMalloc ( sizeof ( rb_red_blk_node ) ) ;
temp - > parent = temp - > left = temp - > right = db_nil ;
temp - > key = NULL ;
temp - > red = 0 ;
return temp ;
}
/***********************************************************************/
/* FUNCTION: LeftRotate */
/**/
/* INPUTS: This takes a tree so that it can access the appropriate */
/* root and nil pointers, and the node to rotate on. */
/**/
/* OUTPUT: None */
/**/
/* Modifies Input: tree, x */
/**/
/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
/* makes the parent of x be to the left of x, x the parent of */
/* its parent before the rotation and fixes other pointers */
/* accordingly. */
/***********************************************************************/
static void
LeftRotate ( rb_red_blk_node * x ) {
rb_red_blk_node * y ;
rb_red_blk_node * nil = db_nil ;
/* I originally wrote this function to use the sentinel for */
/* nil to avoid checking for nil. However this introduces a */
/* very subtle bug because sometimes this function modifies */
/* the parent pointer of nil. This can be a problem if a */
/* function which calls LeftRotate also uses the nil sentinel */
/* and expects the nil sentinel's parent pointer to be unchanged */
/* after calling this function. For example, when RBDeleteFixUP */
/* calls LeftRotate it expects the parent pointer of nil to be */
/* unchanged. */
y = x - > right ;
x - > right = y - > left ;
if ( y - > left ! = nil ) y - > left - > parent = x ; /* used to use sentinel here */
/* and do an unconditional assignment instead of testing for nil */
y - > parent = x - > parent ;
/* instead of checking if x->parent is the root as in the book, we */
/* count on the root sentinel to implicitly take care of this case */
if ( x = = x - > parent - > left ) {
x - > parent - > left = y ;
} else {
x - > parent - > right = y ;
}
y - > left = x ;
x - > parent = y ;
# ifdef DEBUG_ASSERT
Assert ( ! db_nil - > red , " nil not red in LeftRotate " ) ;
# endif
}
/***********************************************************************/
/* FUNCTION: RighttRotate */
/**/
/* INPUTS: This takes a tree so that it can access the appropriate */
/* root and nil pointers, and the node to rotate on. */
/**/
/* OUTPUT: None */
/**/
/* Modifies Input?: tree, y */
/**/
/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
/* makes the parent of x be to the left of x, x the parent of */
/* its parent before the rotation and fixes other pointers */
/* accordingly. */
/***********************************************************************/
static void
RightRotate ( rb_red_blk_node * y ) {
rb_red_blk_node * x ;
rb_red_blk_node * nil = db_nil ;
/* I originally wrote this function to use the sentinel for */
/* nil to avoid checking for nil. However this introduces a */
/* very subtle bug because sometimes this function modifies */
/* the parent pointer of nil. This can be a problem if a */
/* function which calls LeftRotate also uses the nil sentinel */
/* and expects the nil sentinel's parent pointer to be unchanged */
/* after calling this function. For example, when RBDeleteFixUP */
/* calls LeftRotate it expects the parent pointer of nil to be */
/* unchanged. */
x = y - > left ;
y - > left = x - > right ;
if ( nil ! = x - > right ) x - > right - > parent = y ; /*used to use sentinel here */
/* and do an unconditional assignment instead of testing for nil */
/* instead of checking if x->parent is the root as in the book, we */
/* count on the root sentinel to implicitly take care of this case */
x - > parent = y - > parent ;
if ( y = = y - > parent - > left ) {
y - > parent - > left = x ;
} else {
y - > parent - > right = x ;
}
x - > right = y ;
y - > parent = x ;
# ifdef DEBUG_ASSERT
Assert ( ! db_nil - > red , " nil not red in RightRotate " ) ;
# endif
}
/***********************************************************************/
/* FUNCTION: TreeInsertHelp */
/**/
/* INPUTS: tree is the tree to insert into and z is the node to insert */
/**/
/* OUTPUT: none */
/**/
/* Modifies Input: tree, z */
/**/
/* EFFECTS: Inserts z into the tree as if it were a regular binary tree */
/* using the algorithm described in _Introduction_To_Algorithms_ */
/* by Cormen et al. This funciton is only intended to be called */
/* by the RBTreeInsert function and not by the user */
/***********************************************************************/
static void
TreeInsertHelp ( rb_red_blk_node * z ) {
/* This function should only be called by InsertRBTree (see above) */
rb_red_blk_node * x ;
rb_red_blk_node * y ;
rb_red_blk_node * nil = db_nil ;
z - > left = z - > right = nil ;
y = db_root ;
x = db_root - > left ;
while ( x ! = nil ) {
y = x ;
2004-10-27 16:56:34 +01:00
if ( x - > key < z - > key ) { /* x.key > z.key */
2004-09-16 18:29:08 +01:00
x = x - > left ;
} else { /* x,key <= z.key */
x = x - > right ;
2001-04-09 20:54:03 +01:00
}
2004-09-16 18:29:08 +01:00
}
z - > parent = y ;
if ( ( y = = db_root ) | |
2004-10-27 16:56:34 +01:00
( y - > key < z - > key ) ) { /* y.key > z.key */
2004-09-16 18:29:08 +01:00
y - > left = z ;
2001-04-09 20:54:03 +01:00
} else {
2004-09-16 18:29:08 +01:00
y - > right = z ;
}
# ifdef DEBUG_ASSERT
Assert ( ! db_nil - > red , " nil not red in TreeInsertHelp " ) ;
# endif
}
/* Before calling Insert RBTree the node x should have its key set */
/***********************************************************************/
/* FUNCTION: RBTreeInsert */
/**/
/* INPUTS: tree is the red-black tree to insert a node which has a key */
/* pointed to by key and info pointed to by info. */
/**/
/* OUTPUT: This function returns a pointer to the newly inserted node */
/* which is guarunteed to be valid until this node is deleted. */
/* What this means is if another data structure stores this */
/* pointer then the tree does not need to be searched when this */
/* is to be deleted. */
/**/
/* Modifies Input: tree */
/**/
/* EFFECTS: Creates a node node which contains the appropriate key and */
/* info pointers and inserts it into the tree. */
/***********************************************************************/
static rb_red_blk_node *
RBTreeInsert ( CODEADDR key , CODEADDR end , db_entry_type db_type ) {
rb_red_blk_node * y ;
rb_red_blk_node * x ;
rb_red_blk_node * newNode ;
x = ( rb_red_blk_node * ) RBMalloc ( sizeof ( rb_red_blk_node ) ) ;
x - > key = key ;
x - > lim = end ;
x - > db_type = db_type ;
TreeInsertHelp ( x ) ;
newNode = x ;
x - > red = 1 ;
while ( x - > parent - > red ) { /* use sentinel instead of checking for root */
if ( x - > parent = = x - > parent - > parent - > left ) {
y = x - > parent - > parent - > right ;
if ( y - > red ) {
x - > parent - > red = 0 ;
y - > red = 0 ;
x - > parent - > parent - > red = 1 ;
x = x - > parent - > parent ;
} else {
if ( x = = x - > parent - > right ) {
x = x - > parent ;
LeftRotate ( x ) ;
}
x - > parent - > red = 0 ;
x - > parent - > parent - > red = 1 ;
RightRotate ( x - > parent - > parent ) ;
}
} else { /* case for x->parent == x->parent->parent->right */
y = x - > parent - > parent - > left ;
if ( y - > red ) {
x - > parent - > red = 0 ;
y - > red = 0 ;
x - > parent - > parent - > red = 1 ;
x = x - > parent - > parent ;
} else {
if ( x = = x - > parent - > left ) {
x = x - > parent ;
RightRotate ( x ) ;
}
x - > parent - > red = 0 ;
x - > parent - > parent - > red = 1 ;
LeftRotate ( x - > parent - > parent ) ;
}
2001-04-09 20:54:03 +01:00
}
}
2004-09-16 18:29:08 +01:00
db_root - > left - > red = 0 ;
return newNode ;
# ifdef DEBUG_ASSERT
Assert ( ! db_nil - > red , " nil not red in RBTreeInsert " ) ;
Assert ( ! db_root - > red , " root not red in RBTreeInsert " ) ;
# endif
}
/* init the table */
static void
store_in_dbtable ( CODEADDR entry , CODEADDR end , db_entry_type db_type )
{
RBTreeInsert ( entry , end , db_type ) ;
2001-04-09 20:54:03 +01:00
}
/* find an element in the dbentries table */
2004-09-16 18:29:08 +01:00
static rb_red_blk_node *
2003-04-30 18:46:05 +01:00
find_ref_in_dbtable ( CODEADDR entry )
2001-04-09 20:54:03 +01:00
{
2004-09-16 18:29:08 +01:00
rb_red_blk_node * current = db_root - > left ;
2001-04-09 20:54:03 +01:00
2004-09-16 18:29:08 +01:00
while ( current ! = db_nil ) {
if ( current - > key < entry & & current - > lim > entry ) {
return current ;
2002-06-12 17:48:35 +01:00
}
2004-09-16 18:29:08 +01:00
if ( entry < current - > key )
2001-04-09 20:54:03 +01:00
current = current - > right ;
else
current = current - > left ;
}
2004-09-16 18:29:08 +01:00
return current ;
2001-04-09 20:54:03 +01:00
}
static void
mark_db_fixed ( CELL * ptr ) {
2004-09-16 18:29:08 +01:00
rb_red_blk_node * el ;
2001-04-09 20:54:03 +01:00
2003-04-30 18:46:05 +01:00
el = find_ref_in_dbtable ( ( CODEADDR ) ptr ) ;
2004-09-16 18:29:08 +01:00
if ( el ! = db_nil ) {
2003-04-30 18:46:05 +01:00
switch ( el - > db_type ) {
case db_entry :
2004-09-16 18:29:08 +01:00
( ( DBRef ) ( el - > key ) ) - > Flags | = GcFoundMask ;
2003-04-30 18:46:05 +01:00
break ;
case cl_entry :
2004-09-16 18:29:08 +01:00
( ( DynamicClause * ) ( el - > key ) ) - > ClFlags | = GcFoundMask ;
2003-04-30 18:46:05 +01:00
break ;
case lcl_entry :
2004-09-16 18:29:08 +01:00
( ( LogUpdClause * ) ( el - > key ) ) - > ClFlags | = GcFoundMask ;
2003-04-30 18:46:05 +01:00
break ;
2003-10-19 01:33:10 +01:00
case li_entry :
2004-09-16 18:29:08 +01:00
( ( LogUpdIndex * ) ( el - > key ) ) - > ClFlags | = GcFoundMask ;
2003-10-19 01:33:10 +01:00
break ;
2003-04-30 18:46:05 +01:00
case dcl_entry :
2004-09-16 18:29:08 +01:00
( ( DeadClause * ) ( el - > key ) ) - > ClFlags | = GcFoundMask ;
2003-04-30 18:46:05 +01:00
break ;
}
}
2001-04-09 20:54:03 +01:00
}
static void
init_dbtable ( tr_fr_ptr trail_ptr ) {
2003-04-30 18:46:05 +01:00
DeadClause * cl = DeadClauses ;
2002-06-12 17:48:35 +01:00
2005-07-06 16:10:18 +01:00
db_vec0 = db_vec = ( ADDR ) TR ;
2004-09-16 18:29:08 +01:00
db_root = RBTreeCreate ( ) ;
2002-11-18 18:18:05 +00:00
while ( trail_ptr > ( tr_fr_ptr ) Yap_TrailBase ) {
2001-04-09 20:54:03 +01:00
register CELL trail_cell ;
trail_ptr - - ;
trail_cell = TrailTerm ( trail_ptr ) ;
if ( ! IsVarTerm ( trail_cell ) & & IsPairTerm ( trail_cell ) ) {
CELL * pt0 = RepPair ( trail_cell ) ;
/* DB pointer */
CELL flags ;
2001-07-04 17:48:54 +01:00
# ifdef FROZEN_STACKS /* TRAIL */
2001-04-09 20:54:03 +01:00
/* avoid frozen segments */
if (
# ifdef SBA
( ADDR ) pt0 > = HeapTop
# else
2002-11-18 18:18:05 +00:00
( ADDR ) pt0 > = Yap_TrailBase
2001-04-09 20:54:03 +01:00
# endif
) {
continue ;
}
2001-07-04 17:48:54 +01:00
# endif /* FROZEN_STACKS */
2001-04-09 20:54:03 +01:00
2003-04-30 18:46:05 +01:00
flags = * pt0 ;
2001-04-09 20:54:03 +01:00
/* for the moment, if all references to the term in the stacks
are only pointers , reset the flag */
2002-06-04 01:46:32 +01:00
if ( FlagOn ( DBClMask , flags ) ) {
2004-03-05 15:26:33 +00:00
DBRef dbr = DBStructFlagsToDBStruct ( pt0 ) ;
store_in_dbtable ( ( CODEADDR ) dbr ,
( CODEADDR ) dbr + sizeof ( DBStruct ) + sizeof ( CELL ) * dbr - > DBT . NOfCells ,
db_entry ) ;
2003-04-30 18:46:05 +01:00
} else if ( flags & LogUpdMask ) {
2003-10-19 01:33:10 +01:00
if ( flags & IndexMask ) {
2004-03-05 15:26:33 +00:00
LogUpdIndex * li = ClauseFlagsToLogUpdIndex ( pt0 ) ;
store_in_dbtable ( ( CODEADDR ) li , ( CODEADDR ) li + li - > ClSize , li_entry ) ;
2003-10-19 01:33:10 +01:00
} else {
2004-03-05 15:26:33 +00:00
LogUpdClause * cli = ClauseFlagsToLogUpdClause ( pt0 ) ;
store_in_dbtable ( ( CODEADDR ) cli , ( CODEADDR ) cli + cli - > ClSize , lcl_entry ) ;
2003-10-19 01:33:10 +01:00
}
2002-06-12 17:48:35 +01:00
} else {
2004-03-05 15:26:33 +00:00
DynamicClause * dcl = ClauseFlagsToDynamicClause ( pt0 ) ;
2004-03-05 17:27:53 +00:00
store_in_dbtable ( ( CODEADDR ) dcl , ( CODEADDR ) dcl + dcl - > ClSize , dcl_entry ) ;
2001-04-09 20:54:03 +01:00
}
}
}
2002-06-12 17:48:35 +01:00
while ( cl ! = NULL ) {
2004-03-05 15:26:33 +00:00
store_in_dbtable ( ( CODEADDR ) cl , ( CODEADDR ) cl + cl - > ClSize , dcl_entry ) ;
2003-04-30 18:46:05 +01:00
cl = cl - > NextCl ;
2002-06-12 17:48:35 +01:00
}
2001-04-09 20:54:03 +01:00
if ( db_vec = = db_vec0 ) {
/* could not find any entries: probably using LOG UPD semantics */
db_vec0 = NULL ;
}
}
2002-02-26 21:11:57 +00:00
# ifdef DEBUG
/* #define INSTRUMENT_GC 1 */
2001-04-09 20:54:03 +01:00
# ifdef INSTRUMENT_GC
typedef enum {
gc_var ,
gc_ref ,
gc_atom ,
gc_int ,
gc_num ,
gc_list ,
gc_appl ,
gc_func ,
gc_susp
} gc_types ;
unsigned long chain [ 16 ] ;
unsigned long env_vars ;
unsigned long vars [ gc_susp + 1 ] ;
unsigned long num_bs ;
unsigned long old_vars , new_vars ;
static CELL * TrueHB ;
static void
inc_vars_of_type ( CELL * curr , gc_types val ) {
if ( curr > = H0 & & curr < TrueHB ) {
old_vars + + ;
} else if ( curr > = TrueHB & & curr < H ) {
new_vars + + ;
} else {
return ;
}
vars [ val ] + + ;
}
static void
put_type_info ( unsigned long total )
{
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% type info for %lu cells \n " , total ) ;
fprintf ( Yap_stderr , " %% %lu vars \n " , vars [ gc_var ] ) ;
fprintf ( Yap_stderr , " %% %lu refs \n " , vars [ gc_ref ] ) ;
fprintf ( Yap_stderr , " %% %lu references from env \n " , env_vars ) ;
fprintf ( Yap_stderr , " %% %lu atoms \n " , vars [ gc_atom ] ) ;
fprintf ( Yap_stderr , " %% %lu small ints \n " , vars [ gc_int ] ) ;
fprintf ( Yap_stderr , " %% %lu other numbers \n " , vars [ gc_num ] ) ;
fprintf ( Yap_stderr , " %% %lu lists \n " , vars [ gc_list ] ) ;
fprintf ( Yap_stderr , " %% %lu compound terms \n " , vars [ gc_appl ] ) ;
fprintf ( Yap_stderr , " %% %lu functors \n " , vars [ gc_func ] ) ;
fprintf ( Yap_stderr , " %% %lu suspensions \n " , vars [ gc_susp ] ) ;
2001-04-09 20:54:03 +01:00
}
static void
inc_var ( CELL * current , CELL * next )
{
int len = 1 ;
CELL * mynext = next ;
if ( ONHEAP ( current ) ) {
if ( next = = current ) {
inc_vars_of_type ( current , gc_var ) ;
chain [ 0 ] + + ;
} else {
inc_vars_of_type ( current , gc_ref ) ;
while ( ONHEAP ( mynext ) & & IsVarTerm ( * mynext ) ) {
CELL * prox = GET_NEXT ( * mynext ) ;
if ( prox = = mynext ) {
chain [ 0 ] + + ;
break ;
}
len + + ;
mynext = prox ;
}
if ( len > = 15 )
( chain [ 15 ] ) + + ;
else
( chain [ len ] ) + + ;
}
}
}
# endif /* INSTRUMENT_GC */
int STD_PROTO ( vsc_stop , ( void ) ) ;
int
vsc_stop ( void ) {
return ( 1 ) ;
}
2002-10-10 06:58:49 +01:00
# endif
# ifdef CHECK_GLOBAL
2001-04-09 20:54:03 +01:00
static void
check_global ( void ) {
CELL * current ;
# ifdef INSTRUMENT_GC
vars [ gc_var ] = 0 ;
vars [ gc_ref ] = 0 ;
vars [ gc_atom ] = 0 ;
vars [ gc_int ] = 0 ;
vars [ gc_num ] = 0 ;
vars [ gc_list ] = 0 ;
vars [ gc_appl ] = 0 ;
vars [ gc_func ] = 0 ;
vars [ gc_susp ] = 0 ;
# endif
for ( current = H - 1 ; current > = H0 ; current - - ) {
CELL ccurr = * current ;
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( current ) ) {
2001-04-09 20:54:03 +01:00
CELL ccell = UNMARK_CELL ( ccurr ) ;
2004-10-04 19:56:20 +01:00
if (
ccell < MAX_SPECIALS_TAG & & /* two first pages */
ccell > EndSpecials & & IsVarTerm ( ccell ) ) {
2001-04-09 20:54:03 +01:00
/* oops, we found a blob */
int nofcells = ( UNMARK_CELL ( * current ) - EndSpecials ) / sizeof ( CELL ) ;
CELL * ptr = current - nofcells ;
current = ptr ;
ccurr = * current ;
/* process the functor next */
}
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( current ) ) {
2001-04-09 20:54:03 +01:00
printf ( " Oops, found marked cell at %p \n " , current ) ;
break ;
}
}
# if INSTRUMENT_GC
if ( IsVarTerm ( ccurr ) ) {
if ( IsBlobFunctor ( ( Functor ) ccurr ) ) vars [ gc_num ] + + ;
2004-04-22 21:07:07 +01:00
else if ( ccurr ! = 0 & & ( ccurr < ( CELL ) Yap_GlobalBase | | ccurr > ( CELL ) Yap_TrailTop ) ) {
2001-05-21 21:00:05 +01:00
/* printf("%p: %s/%d\n", current,
RepAtom ( NameOfFunctor ( ( Functor ) ccurr ) ) - > StrOfAE ,
ArityOfFunctor ( ( Functor ) ccurr ) ) ; */
vars [ gc_func ] + + ;
}
2004-09-18 15:03:42 +01:00
else if ( IsUnboundVar ( current ) ) vars [ gc_var ] + + ;
2001-04-09 20:54:03 +01:00
else vars [ gc_ref ] + + ;
} else if ( IsApplTerm ( ccurr ) ) {
2001-06-12 17:31:09 +01:00
/* printf("%p: f->%p\n",current,RepAppl(ccurr)); */
2001-04-09 20:54:03 +01:00
vars [ gc_appl ] + + ;
} else if ( IsPairTerm ( ccurr ) ) {
2001-06-12 17:31:09 +01:00
/* printf("%p: l->%p\n",current,RepPair(ccurr)); */
2001-04-09 20:54:03 +01:00
vars [ gc_list ] + + ;
} else if ( IsAtomTerm ( ccurr ) ) {
2001-06-12 17:31:09 +01:00
/* printf("%p: %s\n",current,RepAtom(AtomOfTerm(ccurr))->StrOfAE); */
2001-04-09 20:54:03 +01:00
vars [ gc_atom ] + + ;
} else if ( IsIntTerm ( ccurr ) ) {
2001-06-12 17:31:09 +01:00
/* printf("%p: %d\n",current,IntOfTerm(ccurr)); */
2001-04-09 20:54:03 +01:00
vars [ gc_int ] + + ;
}
# endif
}
# if INSTRUMENT_GC
put_type_info ( H - H0 ) ;
vars [ gc_var ] = 0 ;
vars [ gc_ref ] = 0 ;
vars [ gc_atom ] = 0 ;
vars [ gc_int ] = 0 ;
vars [ gc_num ] = 0 ;
vars [ gc_list ] = 0 ;
vars [ gc_appl ] = 0 ;
vars [ gc_func ] = 0 ;
vars [ gc_susp ] = 0 ;
# endif
}
2002-10-10 06:58:49 +01:00
# else
# define check_global()
# endif /* CHECK_GLOBAL */
2001-04-09 20:54:03 +01:00
/* mark a heap object and all heap objects accessible from it */
2002-11-11 17:38:10 +00:00
static void
2001-04-09 20:54:03 +01:00
mark_variable ( CELL_PTR current )
{
CELL_PTR next ;
register CELL ccur ;
unsigned int arity ;
begin :
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( current ) ) {
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
}
2001-04-09 20:54:03 +01:00
MARK ( current ) ;
2005-09-21 04:49:33 +01:00
if ( current > = H0 & & current < H ) {
total_marked + + ;
2005-10-18 18:04:43 +01:00
if ( current < HGEN ) {
2005-09-21 04:49:33 +01:00
total_oldies + + ;
2005-10-18 18:04:43 +01:00
}
2005-09-21 04:49:33 +01:00
}
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( current ) ;
2005-09-21 04:49:33 +01:00
ccur = * current ;
2001-04-09 20:54:03 +01:00
next = GET_NEXT ( ccur ) ;
if ( IsVarTerm ( ccur ) ) {
if ( ONHEAP ( next ) ) {
2001-05-02 15:19:10 +01:00
# ifdef EASY_SHUNTING
2001-04-09 20:54:03 +01:00
CELL cnext ;
/* do variable shunting between variables in the global */
2004-09-16 18:29:08 +01:00
cnext = * next ;
2005-09-21 04:49:33 +01:00
2004-09-16 18:29:08 +01:00
if ( ! MARKED_PTR ( next ) ) {
2001-04-09 20:54:03 +01:00
if ( IsVarTerm ( cnext ) & & ( CELL ) next = = cnext ) {
/* new global variable to new global variable */
2001-06-06 20:10:51 +01:00
if ( current < prev_HB & & current > = HB & & next > = HB & & next < prev_HB ) {
2001-04-09 20:54:03 +01:00
# ifdef INSTRUMENT_GC
inc_var ( current , current ) ;
# endif
* next = ( CELL ) current ;
2004-09-30 20:51:54 +01:00
# if GC_NO_TAGS
UNMARK ( next ) ;
MARK ( current ) ;
* current = ( CELL ) current ;
# else
2001-04-09 20:54:03 +01:00
* current = MARK_CELL ( ( CELL ) current ) ;
2004-09-30 20:51:54 +01:00
# endif
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
} else {
/* can't help here */
# ifdef INSTRUMENT_GC
inc_var ( current , next ) ;
# endif
current = next ;
}
} else {
/* binding to a determinate reference */
2001-06-06 20:10:51 +01:00
if ( next > = HB & & current < LCL0 & & cnext ! = TermFoundVar ) {
2004-09-30 20:51:54 +01:00
# if GC_NO_TAGS
UNMARK ( current ) ;
# endif
2001-04-09 20:54:03 +01:00
* current = cnext ;
2005-09-21 04:49:33 +01:00
if ( current > = H0 & & current < H ) {
total_marked - - ;
2005-10-18 18:04:43 +01:00
if ( current < HGEN ) {
2005-09-21 04:49:33 +01:00
total_oldies - - ;
2005-10-18 18:04:43 +01:00
}
2005-09-21 04:49:33 +01:00
}
2001-05-02 15:19:10 +01:00
POP_POINTER ( ) ;
2001-04-09 20:54:03 +01:00
} else {
# ifdef INSTRUMENT_GC
inc_var ( current , next ) ;
# endif
current = next ;
}
}
2001-05-07 14:53:19 +01:00
} else if ( IsVarTerm ( cnext ) & &
UNMARK_CELL ( cnext ) ! = ( CELL ) next & &
current < LCL0 ) {
2001-04-26 15:44:43 +01:00
/* This step is possible because we clean up the trail */
* current = UNMARK_CELL ( cnext ) ;
2004-09-30 20:51:54 +01:00
# if GC_NO_TAGS
UNMARK ( current ) ;
# endif
2005-09-21 04:49:33 +01:00
if ( current > = H0 & & current < H ) {
total_marked - - ;
2005-10-18 18:04:43 +01:00
if ( current < HGEN ) {
2005-09-21 04:49:33 +01:00
total_oldies - - ;
2005-10-18 18:04:43 +01:00
}
2005-09-21 04:49:33 +01:00
}
2001-05-02 15:19:10 +01:00
POP_POINTER ( ) ;
2001-04-09 20:54:03 +01:00
} else
# endif
/* what I'd do without variable shunting */
{
# ifdef INSTRUMENT_GC
inc_var ( current , next ) ;
# endif
current = next ;
}
goto begin ;
# ifdef DEBUG
2004-04-22 21:07:07 +01:00
} else if ( next < ( CELL * ) Yap_GlobalBase | | next > ( CELL * ) Yap_TrailTop ) {
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr , " ooops while marking %lx, %p at %p \n " , ( unsigned long int ) ccur , current , next ) ;
2001-04-09 20:54:03 +01:00
# endif
2003-09-25 00:53:48 +01:00
} else {
# ifdef COROUTING
total_smarked + + ;
# endif
2001-04-09 20:54:03 +01:00
# ifdef INSTRUMENT_GC
inc_var ( current , next ) ;
# endif
2003-09-25 00:53:48 +01:00
}
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
} else if ( IsPairTerm ( ccur ) ) {
# ifdef INSTRUMENT_GC
inc_vars_of_type ( current , gc_list ) ;
# endif
if ( ONHEAP ( next ) ) {
2001-06-27 13:46:35 +01:00
PUSH_CONTINUATION ( next + 1 , 1 ) ;
current = next ;
2001-04-09 20:54:03 +01:00
goto begin ;
} else if ( ONCODE ( next ) ) {
mark_db_fixed ( RepPair ( ccur ) ) ;
}
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
} else if ( IsApplTerm ( ccur ) ) {
register CELL cnext = * next ;
# ifdef INSTRUMENT_GC
if ( ! IsExtensionFunctor ( ( Functor ) cnext ) )
inc_vars_of_type ( current , gc_appl ) ;
else
inc_vars_of_type ( current , gc_num ) ;
# endif
if ( ONCODE ( next ) ) {
if ( ( Functor ) cnext = = FunctorDBRef ) {
DBRef tref = DBRefOfTerm ( ccur ) ;
/* make sure the reference is marked as in use */
2002-06-12 17:48:35 +01:00
if ( ( tref - > Flags & ErasedMask ) & &
tref - > Parent ! = NULL & &
tref - > Parent - > KindOfPE & LogUpdDBBit ) {
* current = MkDBRefTerm ( DBErasedMarker ) ;
MARK ( current ) ;
} else {
tref - > Flags | = GcFoundMask ;
2002-06-04 01:46:32 +01:00
}
2001-04-09 20:54:03 +01:00
} else {
mark_db_fixed ( next ) ;
}
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
}
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( next ) | | ! ONHEAP ( next ) )
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
2001-06-27 13:46:35 +01:00
if ( next < H0 ) POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
if ( IsExtensionFunctor ( ( Functor ) cnext ) ) {
switch ( cnext ) {
case ( CELL ) FunctorLongInt :
MARK ( next ) ;
2004-09-30 20:51:54 +01:00
# if GC_NO_TAGS
MARK ( next + 2 ) ;
# endif
2005-10-18 18:04:43 +01:00
if ( next < HGEN ) {
2005-09-21 04:49:33 +01:00
total_oldies + = 3 ;
}
2001-04-09 20:54:03 +01:00
total_marked + = 3 ;
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( next ) ;
PUSH_POINTER ( next + 1 ) ;
PUSH_POINTER ( next + 2 ) ;
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
case ( CELL ) FunctorDouble :
MARK ( next ) ;
2005-10-18 18:04:43 +01:00
if ( next < HGEN ) {
2005-09-21 04:49:33 +01:00
total_oldies + = 2 + SIZEOF_DOUBLE / SIZEOF_LONG_INT ;
}
2001-04-09 20:54:03 +01:00
total_marked + = 2 + SIZEOF_DOUBLE / SIZEOF_LONG_INT ;
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( next ) ;
PUSH_POINTER ( next + 1 ) ;
PUSH_POINTER ( next + 2 ) ;
# if SIZEOF_DOUBLE==2*SIZEOF_LONG_INT
PUSH_POINTER ( next + 3 ) ;
2004-09-30 20:51:54 +01:00
# if GC_NO_TAGS
MARK ( next + 3 ) ;
# endif
# elif GC_NO_TAGS
MARK ( next + 2 ) ;
2001-05-02 15:19:10 +01:00
# endif
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
# ifdef USE_GMP
case ( CELL ) FunctorBigInt :
MARK ( next ) ;
/* size is given by functor + friends */
2005-10-18 18:04:43 +01:00
if ( next < HGEN ) {
2005-09-21 04:49:33 +01:00
total_oldies + = 2 +
( sizeof ( MP_INT ) +
( ( ( MP_INT * ) ( next + 1 ) ) - > _mp_alloc * sizeof ( mp_limb_t ) ) ) / CellSize ;
}
2001-04-09 20:54:03 +01:00
total_marked + = 2 +
( sizeof ( MP_INT ) +
( ( ( MP_INT * ) ( next + 1 ) ) - > _mp_alloc * sizeof ( mp_limb_t ) ) ) / CellSize ;
2001-05-02 15:19:10 +01:00
{
2001-06-11 16:09:36 +01:00
int i ;
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( next ) ;
2001-06-11 16:09:36 +01:00
for ( i = 1 ; i < = ( sizeof ( MP_INT ) +
2001-05-02 15:19:10 +01:00
( ( ( MP_INT * ) ( next + 1 ) ) - > _mp_alloc * sizeof ( mp_limb_t ) ) ) / CellSize ;
2004-09-30 20:51:54 +01:00
i + + ) {
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( next + i ) ;
2004-09-30 20:51:54 +01:00
}
# if GC_NO_TAGS
MARK ( next + i ) ;
# endif
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( next + i ) ;
}
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
# endif
default :
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
}
}
2002-06-04 01:46:32 +01:00
if ( next < H0 ) POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
# ifdef INSTRUMENT_GC
inc_vars_of_type ( next , gc_func ) ;
# endif
arity = ArityOfFunctor ( ( Functor ) ( cnext ) ) ;
MARK ( next ) ;
+ + total_marked ;
2005-10-18 18:04:43 +01:00
if ( next < HGEN ) {
+ + total_oldies ;
}
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( next ) ;
2001-06-27 13:46:35 +01:00
current = next + 1 ;
PUSH_CONTINUATION ( current + 1 , arity - 1 ) ;
2001-04-09 20:54:03 +01:00
goto begin ;
}
# ifdef INSTRUMENT_GC
else if ( IsAtomTerm ( ccur ) )
inc_vars_of_type ( current , gc_atom ) ;
else
inc_vars_of_type ( current , gc_int ) ;
# endif
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
}
2002-11-11 17:38:10 +00:00
void
2002-11-18 18:18:05 +00:00
Yap_mark_variable ( CELL_PTR current )
2002-11-11 17:38:10 +00:00
{
mark_variable ( current ) ;
}
static void
2005-09-09 18:23:43 +01:00
mark_code ( CELL_PTR ptr , CELL * next )
{
if ( ONCODE ( next ) ) {
CELL reg = * ptr ;
if ( IsApplTerm ( reg ) & & ( Functor ) ( * next ) = = FunctorDBRef ) {
DBRef tref = DBRefOfTerm ( reg ) ;
/* make sure the reference is marked as in use */
if ( ( tref - > Flags & ErasedMask ) & &
tref - > Parent ! = NULL & &
tref - > Parent - > KindOfPE & LogUpdDBBit ) {
* ptr = MkDBRefTerm ( DBErasedMarker ) ;
} else {
tref - > Flags | = GcFoundMask ;
}
2001-04-09 20:54:03 +01:00
} else {
2005-09-09 18:23:43 +01:00
mark_db_fixed ( next ) ;
2001-04-09 20:54:03 +01:00
}
2005-09-09 18:23:43 +01:00
}
}
2001-04-09 20:54:03 +01:00
2005-09-09 18:23:43 +01:00
static void
mark_external_reference ( CELL * ptr ) {
CELL * next = GET_NEXT ( * ptr ) ;
if ( ONHEAP ( next ) ) {
2001-05-02 15:19:10 +01:00
# ifdef HYBRID_SCHEME
2005-10-28 18:38:50 +01:00
CELL_PTR * old = iptop ;
# endif
mark_variable ( ptr ) ;
POPSWAP_POINTER ( old ) ;
2005-09-09 18:23:43 +01:00
} else {
MARK ( ptr ) ;
mark_code ( ptr , next ) ;
}
}
static void inline
mark_external_reference2 ( CELL * ptr ) {
CELL * next = GET_NEXT ( * ptr ) ;
if ( ONHEAP ( next ) ) {
2001-05-02 15:19:10 +01:00
# ifdef HYBRID_SCHEME
2005-09-09 18:23:43 +01:00
CELL_PTR * old = iptop ;
2001-05-02 15:19:10 +01:00
# endif
2005-09-09 18:23:43 +01:00
mark_variable ( ptr ) ;
POPSWAP_POINTER ( old ) ;
2001-04-09 20:54:03 +01:00
} else {
2005-09-09 18:23:43 +01:00
mark_code ( ptr , next ) ;
2001-04-09 20:54:03 +01:00
}
}
/*
* mark all heap objects accessible from the trail ( which includes the active
* general purpose registers )
*/
2002-11-11 17:38:10 +00:00
void
2002-11-18 18:18:05 +00:00
Yap_mark_external_reference ( CELL * ptr ) {
2002-11-11 17:38:10 +00:00
mark_external_reference ( ptr ) ;
}
2001-04-09 20:54:03 +01:00
static void
mark_regs ( tr_fr_ptr old_TR )
{
tr_fr_ptr trail_ptr ;
/* first, whatever we dumped on the trail. Easier just to do
the registers separately ? */
for ( trail_ptr = old_TR ; trail_ptr < TR ; trail_ptr + + )
mark_external_reference ( & TrailTerm ( trail_ptr ) ) ;
}
# ifdef COROUTINING
static void
mark_delays ( CELL * max )
{
2002-11-18 18:18:05 +00:00
CELL * ptr = ( CELL * ) Yap_GlobalBase ;
2001-04-09 20:54:03 +01:00
for ( ; ptr < max ; ptr + + ) {
2005-09-09 18:23:43 +01:00
mark_external_reference2 ( ptr ) ;
2001-04-09 20:54:03 +01:00
}
}
# endif
/* mark all heap objects accessible from a chain of environments */
static void
mark_environments ( CELL_PTR gc_ENV , OPREG size , CELL * pvbmap )
{
CELL_PTR saved_var ;
while ( gc_ENV ! = NULL ) { /* no more environments */
Int bmap = 0 ;
int currv = 0 ;
# ifdef DEBUG
if ( size < 0 | | size > 512 )
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr , " Oops, env size for %p is %ld \n " , gc_ENV , ( unsigned long int ) size ) ;
2001-04-09 20:54:03 +01:00
# endif
2003-04-30 18:46:05 +01:00
mark_db_fixed ( ( CELL * ) gc_ENV [ E_CP ] ) ;
2001-04-09 20:54:03 +01:00
/* for each saved variable */
if ( size > EnvSizeInCells ) {
int tsize = size - EnvSizeInCells ;
currv = sizeof ( CELL ) * 8 - tsize % ( sizeof ( CELL ) * 8 ) ;
2003-02-12 13:20:52 +00:00
if ( pvbmap ! = NULL ) {
pvbmap + = tsize / ( sizeof ( CELL ) * 8 ) ;
bmap = * pvbmap ;
} else {
bmap = - 1L ;
}
2001-04-09 20:54:03 +01:00
bmap = ( Int ) ( ( ( CELL ) bmap ) < < currv ) ;
}
for ( saved_var = gc_ENV - size ; saved_var < gc_ENV - EnvSizeInCells ; saved_var + + ) {
if ( currv = = sizeof ( CELL ) * 8 ) {
2003-02-12 13:20:52 +00:00
if ( pvbmap ) {
pvbmap - - ;
bmap = * pvbmap ;
} else {
bmap = - 1L ;
}
2001-04-09 20:54:03 +01:00
currv = 0 ;
}
/* we may have already been here */
2004-09-16 18:29:08 +01:00
if ( bmap < 0 & & ! MARKED_PTR ( saved_var ) ) {
2001-04-09 20:54:03 +01:00
# ifdef INSTRUMENT_GC
Term ccur = * saved_var ;
if ( IsVarTerm ( ccur ) ) {
int len = 1 ;
CELL * mynext = GET_NEXT ( ccur ) ;
if ( ONHEAP ( mynext ) ) {
env_vars + + ;
while ( ONHEAP ( mynext ) & & IsVarTerm ( * mynext ) ) {
CELL * prox = GET_NEXT ( * mynext ) ;
if ( prox = = mynext ) {
chain [ 0 ] + + ;
break ;
}
len + + ;
mynext = prox ;
}
2005-05-26 18:50:06 +01:00
if ( len > = 15 ) {
2001-04-09 20:54:03 +01:00
( chain [ 15 ] ) + + ;
2005-05-26 18:50:06 +01:00
} else {
2001-04-09 20:54:03 +01:00
( chain [ len ] ) + + ;
2005-05-26 18:50:06 +01:00
}
2001-04-09 20:54:03 +01:00
}
}
# endif
mark_external_reference ( saved_var ) ;
}
bmap < < = 1 ;
currv + + ;
}
/* have we met this environment before?? */
/* we use the B field in the environment to tell whether we have
been here before or not .
We do it at the end because we don ' t want to lose any variables
that would have been trimmed at the first environment visit .
*/
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( gc_ENV + E_CB ) )
2001-04-09 20:54:03 +01:00
return ;
MARK ( gc_ENV + E_CB ) ;
size = EnvSize ( ( CELL_PTR ) ( gc_ENV [ E_CP ] ) ) ; /* size = EnvSize(CP) */
pvbmap = EnvBMap ( ( CELL_PTR ) ( gc_ENV [ E_CP ] ) ) ;
2002-04-19 15:43:39 +01:00
#if 0
2002-02-26 15:51:54 +00:00
if ( size < 0 ) {
PredEntry * pe = EnvPreg ( gc_ENV [ E_CP ] ) ;
2002-11-18 18:18:05 +00:00
op_numbers op = Yap_op_from_opcode ( ENV_ToOp ( gc_ENV [ E_CP ] ) ) ;
2005-07-06 18:54:40 +01:00
# if defined(ANALYST) || defined(DEBUG)
2005-07-06 16:10:18 +01:00
fprintf ( Yap_stderr , " ENV %p-%p(%d) %s \n " , gc_ENV , pvbmap , size - EnvSizeInCells , Yap_op_names [ op ] ) ;
2005-07-06 18:54:40 +01:00
# else
fprintf ( Yap_stderr , " ENV %p-%p(%d) %d \n " , gc_ENV , pvbmap , size - EnvSizeInCells , ( int ) op ) ;
# endif
2002-02-26 15:51:54 +00:00
if ( pe - > ArityOfPE )
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr , " %s/%d \n " , RepAtom ( NameOfFunctor ( pe - > FunctorOfPred ) ) - > StrOfAE , pe - > ArityOfPE ) ;
2002-02-26 15:51:54 +00:00
else
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr , " %s \n " , RepAtom ( ( Atom ) ( pe - > FunctorOfPred ) ) - > StrOfAE ) ;
2002-02-26 15:51:54 +00:00
}
# endif
2001-04-09 20:54:03 +01:00
gc_ENV = ( CELL_PTR ) gc_ENV [ E_E ] ; /* link to prev
* environment */
}
}
/*
Cleaning the trail should be quick and simple , right ? Well , not
really : - ( . The problem is that the trail includes a dumping ground
of the WAM registers and of extra choice - point fields , which need
to be cleaned from somewhere .
And cleaning the trail itself is not easy . The problem is that we
may not have cleaned the trail after cuts . If we naively followed
these pointers , we could have direct references to the global
stack ! A solution is to verify whether we are poiting at a
legitimate trail entry . Unfortunately this requires some extra work
following choice - points .
*/
static void
mark_trail ( tr_fr_ptr trail_ptr , tr_fr_ptr trail_base , CELL * gc_H , choiceptr gc_B )
{
2001-12-02 16:54:39 +00:00
# ifdef EASY_SHUNTING
tr_fr_ptr begsTR = NULL , endsTR = NULL ;
# endif
2001-07-04 17:48:54 +01:00
cont * old_cont_top0 = cont_top0 ;
2004-04-16 21:38:54 +01:00
GC_NEW_MAHASH ( ( gc_ma_hash_entry * ) cont_top0 ) ;
while ( trail_base < trail_ptr ) {
2001-04-09 20:54:03 +01:00
register CELL trail_cell ;
2004-04-16 21:38:54 +01:00
trail_cell = TrailTerm ( trail_base ) ;
2001-04-09 20:54:03 +01:00
if ( IsVarTerm ( trail_cell ) ) {
CELL * hp = ( CELL * ) trail_cell ;
/* if a variable older than the current CP has not been marked yet,
than its new binding is not accessible and we can reset it . Note
we must use gc_H to avoid trouble with dangling variables
in the heap */
2004-09-16 18:29:08 +01:00
if ( ( ( hp < gc_H & & hp > = H0 ) | | ( hp > ( CELL * ) gc_B & & hp < LCL0 ) ) & & ! MARKED_PTR ( hp ) ) {
2001-04-17 22:07:41 +01:00
# ifdef EARLY_RESET
2001-04-09 20:54:03 +01:00
/* reset to be a variable */
RESET_VARIABLE ( hp ) ;
discard_trail_entries + + ;
2004-04-16 21:38:54 +01:00
RESET_VARIABLE ( & TrailTerm ( trail_base ) ) ;
2001-07-04 17:48:54 +01:00
# ifdef FROZEN_STACKS
2004-04-16 21:38:54 +01:00
RESET_VARIABLE ( & TrailVal ( trail_base ) ) ;
2001-04-09 20:54:03 +01:00
# endif
2001-04-17 22:07:41 +01:00
# else
/* if I have no early reset I have to follow the trail chain */
2004-04-16 21:38:54 +01:00
mark_external_reference ( & TrailTerm ( trail_base ) ) ;
UNMARK ( & TrailTerm ( trail_base ) ) ;
2001-04-17 22:07:41 +01:00
# endif /* EARLY_RESET */
2004-04-16 21:38:54 +01:00
} else if ( hp < ( CELL * ) Yap_GlobalBase | | hp > ( CELL * ) Yap_TrailTop ) {
2005-10-28 18:38:50 +01:00
/* pointers from the Heap back into the trail are process in mark_regs. */
/* do nothing !!! */
2002-11-18 18:18:05 +00:00
} else if ( ( hp < ( CELL * ) gc_B & & hp > = gc_H ) | | hp > ( CELL * ) Yap_TrailBase ) {
2001-05-21 21:00:05 +01:00
/* clean the trail, avoid dangling pointers! */
2004-04-16 21:38:54 +01:00
RESET_VARIABLE ( & TrailTerm ( trail_base ) ) ;
2001-07-04 17:48:54 +01:00
# ifdef FROZEN_STACKS
2004-04-16 21:38:54 +01:00
RESET_VARIABLE ( & TrailVal ( trail_base ) ) ;
2001-05-21 21:00:05 +01:00
# endif
discard_trail_entries + + ;
} else {
2004-04-16 21:38:54 +01:00
if ( trail_cell = = ( CELL ) trail_base )
2001-06-11 16:09:36 +01:00
discard_trail_entries + + ;
2002-05-03 16:30:36 +01:00
# ifdef FROZEN_STACKS
else
2004-04-16 21:38:54 +01:00
mark_external_reference ( & TrailVal ( trail_base ) ) ;
2002-05-03 16:30:36 +01:00
# endif
2001-05-02 15:19:10 +01:00
# ifdef EASY_SHUNTING
2001-04-26 15:44:43 +01:00
if ( hp < gc_H & & hp > = H0 ) {
2001-12-02 16:54:39 +00:00
tr_fr_ptr nsTR = ( tr_fr_ptr ) cont_top0 ;
CELL * cptr = ( CELL * ) trail_cell ;
2002-11-18 18:18:05 +00:00
if ( ( ADDR ) nsTR > Yap_TrailTop - 1024 )
2004-12-28 22:20:37 +00:00
Yap_growtrail ( 64 * 1024L , TRUE ) ;
2001-12-02 16:54:39 +00:00
TrailTerm ( nsTR ) = ( CELL ) NULL ;
TrailTerm ( nsTR + 1 ) = * hp ;
TrailTerm ( nsTR + 2 ) = trail_cell ;
if ( begsTR = = NULL )
begsTR = nsTR ;
else
TrailTerm ( endsTR ) = ( CELL ) nsTR ;
endsTR = nsTR ;
2002-02-18 15:26:41 +00:00
cont_top = ( cont * ) ( nsTR + 3 ) ;
sTR = ( tr_fr_ptr ) cont_top ;
2004-04-16 21:38:54 +01:00
gc_ma_h_top = ( gc_ma_hash_entry * ) ( nsTR + 3 ) ;
2001-04-26 15:44:43 +01:00
RESET_VARIABLE ( cptr ) ;
MARK ( cptr ) ;
}
2001-04-09 20:54:03 +01:00
# endif
}
} else if ( IsPairTerm ( trail_cell ) ) {
2002-05-23 04:52:34 +01:00
/* can safely ignore this */
2001-04-09 20:54:03 +01:00
}
# if MULTI_ASSIGNMENT_VARIABLES
else {
2002-05-23 04:52:34 +01:00
CELL * cptr = RepAppl ( trail_cell ) ;
2001-04-09 20:54:03 +01:00
/* This is a bit complex. The idea is that we may have several
trailings for the same mavar in the same trail segment . Essentially ,
the problem arises because of ! . What we want is to ignore all but
the last entry , or in this case , all but the first entry with the last
value .
*/
2004-04-16 21:38:54 +01:00
if ( ! gc_lookup_ma_var ( cptr , trail_base ) ) {
2005-05-26 18:50:06 +01:00
/* check whether this is the first time we see it*/
2001-04-09 20:54:03 +01:00
if ( HEAP_PTR ( trail_cell ) ) {
/* fool the gc into thinking this is a variable */
2004-04-16 21:38:54 +01:00
TrailTerm ( trail_base ) = ( CELL ) cptr ;
mark_external_reference ( & ( TrailTerm ( trail_base ) ) ) ;
2001-04-09 20:54:03 +01:00
/* reset the gc to believe the original tag */
2004-04-16 21:38:54 +01:00
TrailTerm ( trail_base ) = AbsAppl ( ( CELL * ) TrailTerm ( trail_base ) ) ;
}
trail_base + + ;
mark_external_reference ( & ( TrailTerm ( trail_base ) ) ) ;
trail_base + + ;
if ( HEAP_PTR ( trail_cell ) ) {
/* fool the gc into thinking this is a variable */
TrailTerm ( trail_base ) = ( CELL ) cptr ;
mark_external_reference ( & ( TrailTerm ( trail_base ) ) ) ;
/* reset the gc to believe the original tag */
TrailTerm ( trail_base ) = AbsAppl ( ( CELL * ) TrailTerm ( trail_base ) ) ;
2002-05-23 04:52:34 +01:00
}
2001-04-09 20:54:03 +01:00
} else {
/* we can safely ignore this little monster */
2004-04-16 21:38:54 +01:00
discard_trail_entries + = 3 ;
RESET_VARIABLE ( & TrailTerm ( trail_base ) ) ;
2001-07-04 17:48:54 +01:00
# ifdef FROZEN_STACKS
2004-04-16 21:38:54 +01:00
RESET_VARIABLE ( & TrailVal ( trail_base ) ) ;
2001-04-09 20:54:03 +01:00
# endif
2004-04-16 21:38:54 +01:00
trail_base + + ;
RESET_VARIABLE ( & TrailTerm ( trail_base ) ) ;
2001-07-04 17:48:54 +01:00
# ifdef FROZEN_STACKS
2004-04-16 21:38:54 +01:00
RESET_VARIABLE ( & TrailVal ( trail_base ) ) ;
2001-04-09 20:54:03 +01:00
# endif
2004-04-16 21:38:54 +01:00
trail_base + + ;
RESET_VARIABLE ( & TrailTerm ( trail_base ) ) ;
2001-07-04 17:48:54 +01:00
# ifdef FROZEN_STACKS
2004-04-16 21:38:54 +01:00
RESET_VARIABLE ( & TrailVal ( trail_base ) ) ;
# endif
}
2001-07-04 17:48:54 +01:00
}
# endif
2004-04-16 21:38:54 +01:00
trail_base + + ;
2001-04-09 20:54:03 +01:00
}
2001-12-02 16:54:39 +00:00
# ifdef EASY_SHUNTING
2002-02-28 18:25:55 +00:00
sTR = ( tr_fr_ptr ) old_cont_top0 ;
2001-12-02 16:54:39 +00:00
while ( begsTR ! = NULL ) {
tr_fr_ptr newsTR = ( tr_fr_ptr ) TrailTerm ( begsTR ) ;
TrailTerm ( sTR ) = TrailTerm ( begsTR + 1 ) ;
TrailTerm ( sTR + 1 ) = TrailTerm ( begsTR + 2 ) ;
begsTR = newsTR ;
sTR + = 2 ;
}
2002-02-28 18:25:55 +00:00
# else
cont_top0 = old_cont_top0 ;
2001-12-02 16:54:39 +00:00
# endif
cont_top = cont_top0 ;
2001-04-09 20:54:03 +01:00
}
/*
* mark all heap objects accessible from each choicepoint & its chain of
* environments
*/
# ifdef TABLING
# define init_substitution_pointer(GCB, SUBS_PTR, DEP_FR) \
2005-04-07 18:56:58 +01:00
if ( DepFr_leader_cp ( DEP_FR ) = = GCB ) { \
/* GCB is a generator-consumer node */ \
/* never here if batched scheduling */ \
SUBS_PTR = ( CELL * ) ( GEN_CP ( GCB ) + 1 ) ; \
SUBS_PTR + = SgFr_arity ( GEN_CP ( GCB ) - > cp_sg_fr ) ; \
} else { \
SUBS_PTR = ( CELL * ) ( CONS_CP ( GCB ) + 1 ) ; \
}
# endif /* TABLING */
2001-04-09 20:54:03 +01:00
2002-05-14 19:24:34 +01:00
static void
mark_slots ( CELL * ptr )
{
Int ns = IntOfTerm ( * ptr ) ;
ptr + + ;
while ( ns > 0 ) {
mark_external_reference ( ptr ) ;
ptr + + ;
ns - - ;
}
}
2001-04-09 20:54:03 +01:00
static void
2002-01-28 04:30:40 +00:00
mark_choicepoints ( register choiceptr gc_B , tr_fr_ptr saved_TR , int very_verbose )
2001-04-09 20:54:03 +01:00
{
2004-09-30 20:51:54 +01:00
yamop * lu_cl0 = NEXTOP ( PredLogUpdClause0 - > CodeOfPred , ld ) ,
* lu_cl = NEXTOP ( PredLogUpdClause - > CodeOfPred , ld ) ,
* su_cl = NEXTOP ( PredStaticClause - > CodeOfPred , ld ) ;
2002-05-03 16:30:36 +01:00
# ifdef TABLING
2004-09-30 20:51:54 +01:00
dep_fr_ptr depfr = LOCAL_top_dep_fr ;
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2001-06-06 20:10:51 +01:00
# ifdef EASY_SHUNTING
2004-09-30 20:51:54 +01:00
HB = H ;
2001-06-06 20:10:51 +01:00
# endif
2004-04-29 04:45:50 +01:00
2001-04-09 20:54:03 +01:00
while ( gc_B ! = NULL ) {
op_numbers opnum ;
register OPCODE op ;
yamop * rtp = gc_B - > cp_ap ;
2003-04-30 18:46:05 +01:00
mark_db_fixed ( ( CELL * ) rtp ) ;
mark_db_fixed ( ( CELL * ) ( gc_B - > cp_cp ) ) ;
2001-05-02 15:19:10 +01:00
# ifdef EASY_SHUNTING
2001-04-09 20:54:03 +01:00
current_B = gc_B ;
2001-06-06 20:10:51 +01:00
prev_HB = HB ;
2001-04-09 20:54:03 +01:00
# endif
HB = gc_B - > cp_h ;
# ifdef INSTRUMENT_GC
num_bs + + ;
# endif
# ifdef TABLING
2002-05-03 16:30:36 +01:00
/* include consumers */
if ( depfr ! = NULL & & gc_B > = DepFr_cons_cp ( depfr ) ) {
gc_B = DepFr_cons_cp ( depfr ) ;
depfr = DepFr_next ( depfr ) ;
2001-04-09 20:54:03 +01:00
continue ;
}
2002-05-03 16:30:36 +01:00
if ( rtp = = NULL ) {
opnum = _table_completion ;
} else
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2002-05-03 16:30:36 +01:00
{
op = rtp - > opc ;
2002-11-18 18:18:05 +00:00
opnum = Yap_op_from_opcode ( op ) ;
2002-05-03 16:30:36 +01:00
}
2002-01-28 04:30:40 +00:00
if ( very_verbose ) {
2004-09-27 21:45:04 +01:00
PredEntry * pe = Yap_PredForChoicePt ( gc_B ) ;
2005-07-06 19:13:21 +01:00
# if defined(ANALYST) || defined(DEBUG)
2004-09-27 21:45:04 +01:00
if ( pe = = NULL ) {
2005-07-06 16:10:18 +01:00
fprintf ( Yap_stderr , " %% marked %ld (%s) \n " , total_marked , Yap_op_names [ opnum ] ) ;
2004-09-27 21:45:04 +01:00
} else if ( pe - > ArityOfPE ) {
2005-07-06 16:10:18 +01:00
fprintf ( Yap_stderr , " %% %s/%d marked %ld (%s) \n " , RepAtom ( NameOfFunctor ( pe - > FunctorOfPred ) ) - > StrOfAE , pe - > ArityOfPE , total_marked , Yap_op_names [ opnum ] ) ;
2004-09-27 21:45:04 +01:00
} else {
2005-07-06 16:10:18 +01:00
fprintf ( Yap_stderr , " %% %s marked %ld (%s) \n " , RepAtom ( ( Atom ) ( pe - > FunctorOfPred ) ) - > StrOfAE , total_marked , Yap_op_names [ opnum ] ) ;
2001-04-09 20:54:03 +01:00
}
2005-07-06 19:13:21 +01:00
# else
if ( pe = = NULL ) {
fprintf ( Yap_stderr , " %% marked %ld (%u) \n " , total_marked , ( unsigned int ) opnum ) ;
} else if ( pe - > ArityOfPE ) {
fprintf ( Yap_stderr , " %% %s/%d marked %ld (%u) \n " , RepAtom ( NameOfFunctor ( pe - > FunctorOfPred ) ) - > StrOfAE , pe - > ArityOfPE , total_marked , ( unsigned int ) opnum ) ;
} else {
fprintf ( Yap_stderr , " %% %s marked %ld (%u) \n " , RepAtom ( ( Atom ) ( pe - > FunctorOfPred ) ) - > StrOfAE , total_marked , ( unsigned int ) opnum ) ;
}
# endif
2001-04-09 20:54:03 +01:00
}
2001-05-21 21:00:05 +01:00
{
/* find out how many cells are still alive in the trail */
2001-07-04 17:48:54 +01:00
# ifndef FROZEN_STACKS
2001-05-21 21:00:05 +01:00
UInt d0 = discard_trail_entries , diff , orig ;
orig = saved_TR - gc_B - > cp_tr ;
2001-07-04 17:48:54 +01:00
# endif
2001-05-21 21:00:05 +01:00
mark_trail ( saved_TR , gc_B - > cp_tr , gc_B - > cp_h , gc_B ) ;
saved_TR = gc_B - > cp_tr ;
2001-07-04 17:48:54 +01:00
# ifndef FROZEN_STACKS
2001-05-21 21:00:05 +01:00
diff = discard_trail_entries - d0 ;
gc_B - > cp_tr = ( tr_fr_ptr ) ( orig - diff ) ;
2001-07-04 17:48:54 +01:00
# endif /* FROZEN_STACKS */
2001-05-21 21:00:05 +01:00
}
2001-04-09 20:54:03 +01:00
if ( opnum = = _or_else | | opnum = = _or_last ) {
/* ; choice point */
mark_environments ( ( CELL_PTR ) ( gc_B - > cp_a1 ) ,
# ifdef YAPOR
- gc_B - > cp_cp - > u . ldl . s / ( ( OPREG ) sizeof ( CELL ) ) ,
2002-02-26 15:51:54 +00:00
( CELL * ) ( gc_B - > cp_cp - > u . ldl . bl )
2001-04-09 20:54:03 +01:00
# else
- gc_B - > cp_cp - > u . sla . s / ( ( OPREG ) sizeof ( CELL ) ) ,
2004-09-30 20:51:54 +01:00
gc_B - > cp_cp - > u . sla . bmap
2001-04-09 20:54:03 +01:00
# endif
) ;
} else {
/* choicepoint with arguments */
register CELL_PTR saved_reg ;
OPREG nargs ;
if ( opnum = = _Nstop )
mark_environments ( ( CELL_PTR ) gc_B - > cp_env ,
EnvSizeInCells ,
NULL ) ;
else
# ifdef TABLING
if ( opnum ! = _table_completion )
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2004-09-30 20:51:54 +01:00
mark_environments ( ( CELL_PTR ) gc_B - > cp_env ,
EnvSize ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ,
EnvBMap ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ) ;
2001-04-09 20:54:03 +01:00
/* extended choice point */
2004-01-29 13:37:10 +00:00
restart_cp :
2001-04-09 20:54:03 +01:00
switch ( opnum ) {
case _Nstop :
2002-05-14 19:24:34 +01:00
mark_slots ( gc_B - > cp_env ) ;
2001-04-09 20:54:03 +01:00
if ( gc_B - > cp_b ! = NULL ) {
2002-05-14 19:24:34 +01:00
nargs = 0 ;
2001-04-09 20:54:03 +01:00
break ;
} else {
/* this is the last choice point, the work is done ;-) */
return ;
}
case _retry_c :
case _retry_userc :
2003-08-27 14:37:10 +01:00
if ( gc_B - > cp_ap = = RETRY_C_RECORDED_K_CODE
2001-04-09 20:54:03 +01:00
| | gc_B - > cp_ap = = RETRY_C_RECORDEDP_CODE ) {
/* we have a reference from the choice-point stack to a term */
choiceptr old_b = B ;
DBRef ref ;
B = gc_B ;
ref = ( DBRef ) EXTRA_CBACK_ARG ( 3 , 1 ) ;
if ( IsVarTerm ( ( CELL ) ref ) )
ref - > Flags | = GcFoundMask ;
else {
if ( ONCODE ( ( CELL ) ref ) ) {
mark_db_fixed ( RepAppl ( ( CELL ) ref ) ) ;
}
}
B = old_b ;
}
nargs = rtp - > u . lds . s + rtp - > u . lds . extra ;
break ;
2004-01-29 13:37:10 +00:00
case _jump :
rtp = rtp - > u . l . l ;
op = rtp - > opc ;
opnum = Yap_op_from_opcode ( op ) ;
goto restart_cp ;
2001-04-09 20:54:03 +01:00
case _trust_logical_pred :
case _retry_profiled :
2002-09-03 15:28:09 +01:00
case _count_retry :
2001-04-09 20:54:03 +01:00
rtp = NEXTOP ( rtp , l ) ;
op = rtp - > opc ;
2002-11-18 18:18:05 +00:00
opnum = Yap_op_from_opcode ( op ) ;
2001-04-09 20:54:03 +01:00
goto restart_cp ;
2002-01-22 15:06:22 +00:00
case _trust_fail :
nargs = 0 ;
break ;
2001-04-09 20:54:03 +01:00
# ifdef TABLING
2005-08-01 16:40:39 +01:00
case _table_load_answer :
{
CELL * vars_ptr , vars ;
vars_ptr = ( CELL * ) ( LOAD_CP ( gc_B ) + 1 ) ;
vars = * vars_ptr + + ;
while ( vars - - ) {
mark_external_reference ( vars_ptr ) ;
vars_ptr + + ;
}
}
nargs = 0 ;
break ;
case _table_try_answer :
2005-07-06 20:34:12 +01:00
case _table_retry_me :
case _table_trust_me :
case _table_retry :
case _table_trust :
2001-04-09 20:54:03 +01:00
{
2005-07-06 20:34:12 +01:00
CELL * vars_ptr , vars ;
vars_ptr = ( CELL * ) ( GEN_CP ( gc_B ) + 1 ) ;
nargs = rtp - > u . ld . s ;
while ( nargs - - ) {
mark_external_reference ( vars_ptr ) ;
vars_ptr + + ;
}
vars = * vars_ptr + + ;
2001-04-09 20:54:03 +01:00
while ( vars - - ) {
2005-07-06 20:34:12 +01:00
mark_external_reference ( vars_ptr ) ;
vars_ptr + + ;
2001-04-09 20:54:03 +01:00
}
}
2005-07-06 20:34:12 +01:00
nargs = 0 ;
2001-04-09 20:54:03 +01:00
break ;
case _table_completion :
{
2005-07-06 20:34:12 +01:00
CELL * vars_ptr , vars ;
vars_ptr = ( CELL * ) ( GEN_CP ( gc_B ) + 1 ) ;
nargs = SgFr_arity ( GEN_CP ( gc_B ) - > cp_sg_fr ) ;
2001-04-09 20:54:03 +01:00
while ( nargs - - ) {
2005-07-06 20:34:12 +01:00
mark_external_reference ( vars_ptr ) ;
vars_ptr + + ;
}
vars = * vars_ptr + + ;
while ( vars - - ) {
mark_external_reference ( vars_ptr ) ;
vars_ptr + + ;
2001-04-09 20:54:03 +01:00
}
}
2002-05-03 16:30:36 +01:00
nargs = 0 ;
2001-04-09 20:54:03 +01:00
break ;
2005-07-06 20:34:12 +01:00
case _table_answer_resolution :
2001-04-09 20:54:03 +01:00
{
2005-07-06 20:34:12 +01:00
CELL * vars_ptr , vars ;
init_substitution_pointer ( gc_B , vars_ptr , CONS_CP ( gc_B ) - > cp_dep_fr ) ;
vars = * vars_ptr + + ;
while ( vars - - ) {
mark_external_reference ( vars_ptr ) ;
vars_ptr + + ;
2001-04-09 20:54:03 +01:00
}
2005-07-06 20:34:12 +01:00
}
nargs = 0 ;
break ;
case _trie_retry_null :
case _trie_trust_null :
2002-05-03 16:30:36 +01:00
case _trie_retry_var :
case _trie_trust_var :
case _trie_retry_val :
case _trie_trust_val :
case _trie_retry_atom :
case _trie_trust_atom :
case _trie_retry_list :
case _trie_trust_list :
case _trie_retry_struct :
case _trie_trust_struct :
2005-07-06 20:34:12 +01:00
case _trie_retry_extension :
case _trie_trust_extension :
2005-06-03 09:26:32 +01:00
case _trie_retry_float :
case _trie_trust_float :
2005-06-04 08:28:24 +01:00
case _trie_retry_long :
case _trie_trust_long :
2002-05-03 16:30:36 +01:00
{
2005-07-06 20:34:12 +01:00
CELL * vars_ptr ;
int heap_arity , vars_arity , subs_arity ;
vars_ptr = ( CELL * ) ( gc_B + 1 ) ;
heap_arity = * vars_ptr ;
vars_arity = * ( vars_ptr + heap_arity + 1 ) ;
subs_arity = * ( vars_ptr + heap_arity + 2 ) ;
vars_ptr + = heap_arity + subs_arity + vars_arity + 2 ;
if ( vars_arity ) {
while ( vars_arity - - ) {
mark_external_reference ( vars_ptr ) ;
vars_ptr - - ;
2002-05-03 16:30:36 +01:00
}
2005-07-06 20:34:12 +01:00
}
if ( subs_arity ) {
while ( subs_arity - - ) {
mark_external_reference ( vars_ptr ) ;
vars_ptr - - ;
2002-05-03 16:30:36 +01:00
}
2005-07-06 20:34:12 +01:00
}
vars_ptr - = 2 ;
if ( heap_arity ) {
while ( heap_arity - - ) {
if ( * vars_ptr = = 0 )
break ; /* term extension mark: float/longint */
mark_external_reference ( vars_ptr ) ;
vars_ptr - - ;
2002-05-03 16:30:36 +01:00
}
}
}
nargs = 0 ;
2001-04-09 20:54:03 +01:00
break ;
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2003-02-12 15:40:04 +00:00
case _profiled_retry_and_mark :
case _count_retry_and_mark :
case _retry_and_mark :
2003-04-30 18:46:05 +01:00
ClauseCodeToDynamicClause ( gc_B - > cp_ap ) - > ClFlags | = GcFoundMask ;
2004-09-27 21:45:04 +01:00
case _retry2 :
nargs = 2 ;
break ;
case _retry3 :
nargs = 3 ;
break ;
case _retry4 :
nargs = 4 ;
break ;
2001-04-09 20:54:03 +01:00
# ifdef DEBUG
case _retry_me :
case _trust_me :
case _profiled_retry_me :
case _profiled_trust_me :
2002-09-03 15:28:09 +01:00
case _count_retry_me :
case _count_trust_me :
2001-04-09 20:54:03 +01:00
case _retry :
case _trust :
nargs = rtp - > u . ld . s ;
break ;
default :
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr , " OOps in GC: Unexpected opcode: %d \n " , opnum ) ;
2001-04-09 20:54:03 +01:00
nargs = 0 ;
# else
default :
nargs = rtp - > u . ld . s ;
# endif
}
2001-12-02 16:54:39 +00:00
2004-04-30 20:50:01 +01:00
if ( gc_B - > cp_ap = = lu_cl0 | |
gc_B - > cp_ap = = lu_cl | |
gc_B - > cp_ap = = su_cl ) {
CELL * pt = ( CELL * ) IntegerOfTerm ( gc_B - > cp_args [ 1 ] ) ;
mark_db_fixed ( pt ) ;
}
2001-04-09 20:54:03 +01:00
/* for each saved register */
for ( saved_reg = & gc_B - > cp_a1 ;
/* assumes we can count registers in CP this
way */
saved_reg < & gc_B - > cp_a1 + nargs ;
saved_reg + + ) {
mark_external_reference ( saved_reg ) ;
}
}
gc_B = gc_B - > cp_b ;
}
}
/*
* insert a cell which points to a heap object into relocation chain of that
* object
*/
2005-07-06 16:10:18 +01:00
static inline void
2001-04-09 20:54:03 +01:00
into_relocation_chain ( CELL_PTR current , CELL_PTR next )
{
2005-09-09 18:23:43 +01:00
# if GC_NO_TAGS
CELL current_tag ;
current_tag = TAG ( * current ) ;
if ( RMARKED ( next ) )
RMARK ( current ) ;
else {
UNRMARK ( current ) ;
RMARK ( next ) ;
}
* current = * next ;
* next = ( CELL ) current | current_tag ;
# else
2001-04-09 20:54:03 +01:00
# ifdef TAGS_FAST_OPS
register CELL ccur = * current , cnext = * next ;
if ( IsVarTerm ( ccur ) ) {
* current = ( MARKED ( ccur ) ? MARK_CELL ( UNMARKED ( cnext ) ) :
UNMARKED ( cnext ) ) ;
* next = ( MARKED ( cnext ) ? MBIT : 0 ) | RBIT | ( Int ) current ;
} else if ( IsPairTerm ( ccur ) ) {
* current = ( MARKED ( ccur ) ? MARK_CELL ( UNMARKED ( cnext ) ) :
UNMARKED ( cnext ) ) ;
* next = AbsPair ( ( CELL * )
( ( MARKED ( cnext ) ? MBIT : 0 ) | RBIT | ( Int ) current ) ) ;
} else if ( IsApplTerm ( ccur ) ) {
* current = ( MARKED ( ccur ) ? MARK_CELL ( UNMARKED ( cnext ) ) :
UNMARKED ( cnext ) ) ;
* next = AbsAppl ( ( CELL * )
( ( MARKED ( cnext ) ? MBIT : 0 ) | RBIT | ( Int ) current ) ) ;
} else {
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr , " OH MY GOD !!!!!!!!!!!! \n " ) ;
2001-04-09 20:54:03 +01:00
}
# else
CELL current_tag ;
current_tag = TAG ( * current ) ;
* current = ( * current & MBIT ) | ( * next & ~ MBIT ) ;
# if INVERT_RBIT
* next = ( ( * next & MBIT ) | ( CELL ) current | current_tag ) & ~ RBIT ;
# else
* next = ( * next & MBIT ) | RBIT | ( CELL ) current | current_tag ;
# endif
# endif
2005-09-09 18:23:43 +01:00
# endif /* GC_NO_TAGS */
2001-04-09 20:54:03 +01:00
}
/* insert trail cells which point to heap objects into relocation chains */
static void
sweep_trail ( choiceptr gc_B , tr_fr_ptr old_TR )
{
2001-06-06 20:10:51 +01:00
tr_fr_ptr trail_ptr , dest ;
2005-03-13 06:26:13 +00:00
# if !USE_MALLOC
2001-04-09 20:54:03 +01:00
Int OldHeapUsed = HeapUsed ;
2005-03-13 06:26:13 +00:00
# endif
2001-04-09 20:54:03 +01:00
# ifdef DEBUG
Int hp_entrs = 0 , hp_erased = 0 , hp_not_in_use = 0 ,
hp_in_use_erased = 0 , code_entries = 0 ;
# endif
2001-07-04 17:48:54 +01:00
# ifndef FROZEN_STACKS
/*
adjust cp_tr pointers ,
we don ' t compress TR if we have freeze .
*/
2001-05-21 21:00:05 +01:00
{
2002-11-18 18:18:05 +00:00
Int size = old_TR - ( tr_fr_ptr ) Yap_TrailBase ;
2001-05-21 21:00:05 +01:00
size - = discard_trail_entries ;
while ( gc_B ! = NULL ) {
size - = ( UInt ) ( gc_B - > cp_tr ) ;
2002-11-18 18:18:05 +00:00
gc_B - > cp_tr = ( tr_fr_ptr ) Yap_TrailBase + size ;
2001-05-21 21:00:05 +01:00
gc_B = gc_B - > cp_b ;
}
}
2001-07-04 17:48:54 +01:00
# endif /* FROZEN_STACKS */
2001-04-09 20:54:03 +01:00
/* first, whatever we dumped on the trail. Easier just to do
the registers separately ? */
for ( trail_ptr = old_TR ; trail_ptr < TR ; trail_ptr + + ) {
2005-10-28 18:38:50 +01:00
if ( IN_BETWEEN ( Yap_GlobalBase , TrailTerm ( trail_ptr ) , Yap_TrailTop ) & &
MARKED_PTR ( & TrailTerm ( trail_ptr ) ) ) {
2001-04-09 20:54:03 +01:00
UNMARK ( & TrailTerm ( trail_ptr ) ) ;
if ( HEAP_PTR ( TrailTerm ( trail_ptr ) ) ) {
into_relocation_chain ( & TrailTerm ( trail_ptr ) , GET_NEXT ( TrailTerm ( trail_ptr ) ) ) ;
}
}
}
/* next, follows the real trail entries */
2002-11-18 18:18:05 +00:00
trail_ptr = ( tr_fr_ptr ) Yap_TrailBase ;
2001-05-21 21:00:05 +01:00
dest = trail_ptr ;
while ( trail_ptr < old_TR ) {
2001-04-09 20:54:03 +01:00
register CELL trail_cell ;
trail_cell = TrailTerm ( trail_ptr ) ;
2002-05-03 16:30:36 +01:00
# ifndef FROZEN_STACKS
2001-07-04 17:48:54 +01:00
/* recover a trail cell */
2001-05-21 21:00:05 +01:00
if ( trail_cell = = ( CELL ) trail_ptr ) {
2001-07-04 17:48:54 +01:00
TrailTerm ( dest ) = trail_cell ;
2001-05-21 21:00:05 +01:00
trail_ptr + + ;
/* just skip cell */
2001-07-04 17:48:54 +01:00
} else
2001-04-09 20:54:03 +01:00
# endif
2001-07-04 17:48:54 +01:00
{
TrailTerm ( dest ) = trail_cell ;
2001-05-21 21:00:05 +01:00
if ( IsVarTerm ( trail_cell ) ) {
/* we need to check whether this is a honest to god trail entry */
2005-10-28 18:38:50 +01:00
/* make sure it is a heap cell before we test whether it has been marked */
if ( ( CELL * ) trail_cell < H & & ( CELL * ) trail_cell > = H0 & & MARKED_PTR ( ( CELL * ) trail_cell ) ) {
2001-05-21 21:00:05 +01:00
if ( HEAP_PTR ( trail_cell ) ) {
into_relocation_chain ( & TrailTerm ( dest ) , GET_NEXT ( trail_cell ) ) ;
}
2002-05-03 16:30:36 +01:00
# ifdef FROZEN_STACKS
/* it is complex to recover cells with frozen segments */
TrailVal ( dest ) = TrailVal ( trail_ptr ) ;
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( & TrailVal ( dest ) ) ) {
2002-05-03 16:30:36 +01:00
UNMARK ( & TrailVal ( dest ) ) ;
if ( HEAP_PTR ( TrailVal ( dest ) ) ) {
into_relocation_chain ( & TrailVal ( dest ) , GET_NEXT ( TrailVal ( dest ) ) ) ;
}
}
2001-04-09 20:54:03 +01:00
# endif
2002-05-03 16:30:36 +01:00
}
2001-05-21 21:00:05 +01:00
} else if ( IsPairTerm ( trail_cell ) ) {
CELL * pt0 = RepPair ( trail_cell ) ;
CELL flags ;
2001-04-09 20:54:03 +01:00
2001-07-04 17:48:54 +01:00
# ifdef FROZEN_STACKS /* TRAIL */
2001-05-21 21:00:05 +01:00
/* process all segments */
if (
2001-04-09 20:54:03 +01:00
# ifdef SBA
2004-04-22 21:07:07 +01:00
( ADDR ) pt0 > = Yap_GlobalBase
2001-04-09 20:54:03 +01:00
# else
2002-11-18 18:18:05 +00:00
( ADDR ) pt0 > = Yap_TrailBase
2001-04-09 20:54:03 +01:00
# endif
2001-05-21 21:00:05 +01:00
) {
2001-06-11 16:09:36 +01:00
trail_ptr + + ;
dest + + ;
2001-05-21 21:00:05 +01:00
continue ;
}
2001-07-04 17:48:54 +01:00
# endif /* FROZEN_STACKS */
2003-04-30 18:46:05 +01:00
flags = * pt0 ;
2001-04-09 20:54:03 +01:00
# ifdef DEBUG
2002-06-12 17:48:35 +01:00
hp_entrs + + ;
if ( ! FlagOn ( GcFoundMask , flags ) ) {
hp_not_in_use + + ;
if ( ! FlagOn ( DBClMask , flags ) ) {
code_entries + + ;
}
if ( FlagOn ( ErasedMask , flags ) ) {
hp_erased + + ;
2001-04-09 20:54:03 +01:00
}
} else {
2002-06-12 17:48:35 +01:00
if ( FlagOn ( ErasedMask , flags ) ) {
hp_in_use_erased + + ;
}
2001-04-09 20:54:03 +01:00
}
# endif
2002-06-12 17:48:35 +01:00
if ( ! FlagOn ( GcFoundMask , flags ) ) {
2002-06-04 01:46:32 +01:00
if ( FlagOn ( DBClMask , flags ) ) {
2002-06-12 17:48:35 +01:00
DBRef dbr = ( DBRef ) ( ( CELL ) pt0 - ( CELL ) & ( ( ( DBRef ) NIL ) - > Flags ) ) ;
dbr - > Flags & = ~ InUseMask ;
DEC_DBREF_COUNT ( dbr ) ;
if ( dbr - > Flags & ErasedMask ) {
2002-11-18 18:18:05 +00:00
Yap_ErDBE ( dbr ) ;
2002-06-12 17:48:35 +01:00
}
} else {
2003-04-30 18:46:05 +01:00
if ( flags & LogUpdMask ) {
2003-10-14 01:53:10 +01:00
if ( flags & IndexMask ) {
LogUpdIndex * indx = ClauseFlagsToLogUpdIndex ( pt0 ) ;
int erase ;
DEC_CLREF_COUNT ( indx ) ;
indx - > ClFlags & = ~ InUseMask ;
2004-04-22 04:24:17 +01:00
erase = ( indx - > ClFlags & ErasedMask
& & ! indx - > ClRefCount ) ;
2003-10-14 01:53:10 +01:00
if ( erase ) {
/* at this point,
no one is accessing the clause */
2004-11-04 18:22:36 +00:00
Yap_ErLogUpdIndex ( indx , NULL ) ;
2003-10-14 01:53:10 +01:00
}
} else {
LogUpdClause * cl = ClauseFlagsToLogUpdClause ( pt0 ) ;
int erase ;
2004-04-22 04:24:17 +01:00
2003-10-14 01:53:10 +01:00
DEC_CLREF_COUNT ( cl ) ;
cl - > ClFlags & = ~ InUseMask ;
2004-04-22 04:24:17 +01:00
erase = ( ( cl - > ClFlags & ErasedMask ) & & ! cl - > ClRefCount ) ;
2003-10-14 01:53:10 +01:00
if ( erase ) {
/* at this point,
no one is accessing the clause */
Yap_ErLogUpdCl ( cl ) ;
}
2003-04-30 18:46:05 +01:00
}
} else {
DynamicClause * cl = ClauseFlagsToDynamicClause ( pt0 ) ;
int erase ;
DEC_CLREF_COUNT ( cl ) ;
cl - > ClFlags & = ~ InUseMask ;
erase = ( cl - > ClFlags & ErasedMask )
# if defined(YAPOR) || defined(THREADS)
2003-12-18 17:23:22 +00:00
& & ( cl - > ClRefCount = = 0 )
2003-04-30 18:46:05 +01:00
# endif
;
if ( erase ) {
/* at this point,
no one is accessing the clause */
Yap_ErCl ( cl ) ;
}
2001-05-21 21:00:05 +01:00
}
2001-04-09 20:54:03 +01:00
}
2002-06-12 17:48:35 +01:00
RESET_VARIABLE ( & TrailTerm ( dest ) ) ;
discard_trail_entries + + ;
2001-05-21 21:00:05 +01:00
} else {
2003-04-30 18:46:05 +01:00
* pt0 = ResetFlag ( GcFoundMask , flags ) ;
2001-04-09 20:54:03 +01:00
}
# if MULTI_ASSIGNMENT_VARIABLES
2001-05-21 21:00:05 +01:00
} else {
2004-03-19 11:35:42 +00:00
CELL trail_cell = TrailTerm ( trail_ptr + 2 ) ;
2001-05-21 21:00:05 +01:00
CELL * ptr ;
CELL old = TrailTerm ( trail_ptr + 1 ) ;
2004-09-17 22:22:32 +01:00
/* be sure we don't overwrite before we read */
2005-05-26 18:50:06 +01:00
Int marked_ptr = MARKED_PTR ( & TrailTerm ( trail_ptr + 2 ) ) ;
Int marked_old = MARKED_PTR ( & TrailTerm ( trail_ptr + 1 ) ) ;
2004-09-17 22:22:32 +01:00
# ifdef FROZEN_STACKS
2005-05-26 18:50:06 +01:00
Int marked_val_old = MARKED_PTR ( & TrailVal ( trail_ptr + 1 ) ) ;
Int marked_val_ptr = MARKED_PTR ( & TrailVal ( trail_ptr + 2 ) ) ;
2004-09-17 22:22:32 +01:00
# endif
2001-04-09 20:54:03 +01:00
2004-09-17 22:22:32 +01:00
if ( marked_ptr )
2001-05-21 21:00:05 +01:00
ptr = RepAppl ( UNMARK_CELL ( trail_cell ) ) ;
else
ptr = RepAppl ( trail_cell ) ;
2004-03-19 11:35:42 +00:00
TrailTerm ( dest + 1 ) = old ;
2004-09-17 22:22:32 +01:00
if ( marked_old ) {
2004-03-19 11:35:42 +00:00
UNMARK ( & TrailTerm ( dest + 1 ) ) ;
2001-05-21 21:00:05 +01:00
if ( HEAP_PTR ( old ) ) {
2004-03-19 11:35:42 +00:00
into_relocation_chain ( & TrailTerm ( dest + 1 ) , GET_NEXT ( old ) ) ;
2001-05-21 21:00:05 +01:00
}
}
2004-09-17 22:22:32 +01:00
TrailTerm ( dest + 2 ) = TrailTerm ( dest ) = trail_cell ;
2001-07-04 17:48:54 +01:00
# ifdef FROZEN_STACKS
2004-03-19 11:35:42 +00:00
TrailVal ( dest + 1 ) = TrailVal ( trail_ptr + 1 ) ;
2004-09-17 22:22:32 +01:00
if ( marked_val_old ) {
2004-03-19 11:35:42 +00:00
UNMARK ( & TrailVal ( dest + 1 ) ) ;
if ( HEAP_PTR ( TrailVal ( dest + 1 ) ) ) {
into_relocation_chain ( & TrailVal ( dest + 1 ) , GET_NEXT ( TrailTerm ( dest + 1 ) ) ) ;
}
}
TrailVal ( dest + 2 ) = TrailVal ( trail_ptr + 2 ) ;
2004-09-17 22:22:32 +01:00
if ( marked_val_ptr ) {
2004-03-19 11:35:42 +00:00
UNMARK ( & TrailVal ( dest + 2 ) ) ;
if ( HEAP_PTR ( TrailVal ( dest + 2 ) ) ) {
into_relocation_chain ( & TrailVal ( dest + 2 ) , GET_NEXT ( TrailTerm ( dest + 2 ) ) ) ;
2001-07-04 17:48:54 +01:00
}
}
# endif
2004-09-17 22:22:32 +01:00
if ( marked_ptr ) {
2001-05-21 21:00:05 +01:00
UNMARK ( & TrailTerm ( dest ) ) ;
2004-03-19 11:35:42 +00:00
UNMARK ( & TrailTerm ( dest + 2 ) ) ;
2001-05-21 21:00:05 +01:00
if ( HEAP_PTR ( trail_cell ) ) {
2001-06-06 20:10:51 +01:00
into_relocation_chain ( & TrailTerm ( dest ) , GET_NEXT ( trail_cell ) ) ;
2004-03-19 11:35:42 +00:00
into_relocation_chain ( & TrailTerm ( dest + 2 ) , GET_NEXT ( trail_cell ) ) ;
2001-05-21 21:00:05 +01:00
}
}
2004-03-19 11:35:42 +00:00
trail_ptr + = 2 ;
dest + = 2 ;
2001-04-09 20:54:03 +01:00
# endif
2001-05-21 21:00:05 +01:00
}
trail_ptr + + ;
dest + + ;
}
}
new_TR = dest ;
2001-04-09 20:54:03 +01:00
if ( is_gc_verbose ( ) ) {
2002-11-18 18:18:05 +00:00
if ( old_TR ! = ( tr_fr_ptr ) Yap_TrailBase )
fprintf ( Yap_stderr ,
2004-09-03 04:11:09 +01:00
" %% Trail: discarded %d (%ld%%) cells out of %ld \n " ,
2001-06-08 20:33:16 +01:00
discard_trail_entries ,
2002-11-18 18:18:05 +00:00
( unsigned long int ) ( discard_trail_entries * 100 / ( old_TR - ( tr_fr_ptr ) Yap_TrailBase ) ) ,
( unsigned long int ) ( old_TR - ( tr_fr_ptr ) Yap_TrailBase ) ) ;
2001-04-09 20:54:03 +01:00
# ifdef DEBUG
if ( hp_entrs > 0 )
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr ,
2004-09-03 04:11:09 +01:00
" %% Trail: unmarked %ld dbentries (%ld%%) out of %ld \n " ,
2001-04-09 20:54:03 +01:00
( long int ) hp_not_in_use ,
( long int ) ( hp_not_in_use * 100 / hp_entrs ) ,
( long int ) hp_entrs ) ;
if ( hp_in_use_erased > 0 & & hp_erased > 0 )
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr ,
2004-09-03 04:11:09 +01:00
" %% Trail: deleted %ld dbentries (%ld%%) out of %ld \n " ,
2001-04-09 20:54:03 +01:00
( long int ) hp_erased ,
( long int ) ( hp_erased * 100 / ( hp_erased + hp_in_use_erased ) ) ,
( long int ) ( hp_erased + hp_in_use_erased ) ) ;
# endif
2004-10-04 19:56:20 +01:00
# if !USE_SYSTEM_MALLOC
2002-11-18 18:18:05 +00:00
fprintf ( Yap_stderr ,
2004-10-04 19:56:20 +01:00
" %% Heap: recovered %ld bytes (%ld%%) out of %ld \n " ,
( unsigned long int ) ( OldHeapUsed - HeapUsed ) ,
( unsigned long int ) ( ( OldHeapUsed - HeapUsed ) / ( OldHeapUsed / 100 ) ) ,
( unsigned long int ) OldHeapUsed ) ;
# endif
2002-06-12 17:48:35 +01:00
}
2003-04-30 18:46:05 +01:00
{
DeadClause * * cptr ;
DeadClause * cl ;
cptr = & ( DeadClauses ) ;
cl = DeadClauses ;
while ( cl ! = NULL ) {
if ( ! ( cl - > ClFlags & GcFoundMask ) ) {
char * ocl = ( char * ) cl ;
cl = cl - > NextCl ;
* cptr = cl ;
Yap_FreeCodeSpace ( ocl ) ;
} else {
cl - > ClFlags & = ~ GcFoundMask ;
cptr = & ( cl - > NextCl ) ;
cl = cl - > NextCl ;
}
2001-04-09 20:54:03 +01:00
}
2002-06-12 17:48:35 +01:00
}
2001-04-09 20:54:03 +01:00
}
/*
* insert cells of a chain of environments which point to heap objects into
* relocation chains
*/
static void
sweep_environments ( CELL_PTR gc_ENV , OPREG size , CELL * pvbmap )
{
CELL_PTR saved_var ;
while ( gc_ENV ! = NULL ) { /* no more environments */
Int bmap = 0 ;
int currv = 0 ;
/* for each saved variable */
if ( size > EnvSizeInCells ) {
int tsize = size - EnvSizeInCells ;
2002-05-03 16:30:36 +01:00
2001-04-09 20:54:03 +01:00
currv = sizeof ( CELL ) * 8 - tsize % ( sizeof ( CELL ) * 8 ) ;
2003-02-12 13:20:52 +00:00
if ( pvbmap ! = NULL ) {
pvbmap + = tsize / ( sizeof ( CELL ) * 8 ) ;
bmap = * pvbmap ;
} else {
bmap = - 1L ;
}
2001-04-09 20:54:03 +01:00
bmap = ( Int ) ( ( ( CELL ) bmap ) < < currv ) ;
}
for ( saved_var = gc_ENV - size ; saved_var < gc_ENV - EnvSizeInCells ; saved_var + + ) {
if ( currv = = sizeof ( CELL ) * 8 ) {
2003-02-12 13:20:52 +00:00
if ( pvbmap ! = NULL ) {
pvbmap - - ;
bmap = * pvbmap ;
} else {
bmap = - 1L ;
}
2001-04-09 20:54:03 +01:00
currv = 0 ;
}
if ( bmap < 0 ) {
CELL env_cell = * saved_var ;
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( saved_var ) ) {
2001-04-09 20:54:03 +01:00
UNMARK ( saved_var ) ;
if ( HEAP_PTR ( env_cell ) ) {
into_relocation_chain ( saved_var , GET_NEXT ( env_cell ) ) ;
}
}
}
bmap < < = 1 ;
currv + + ;
}
/* have we met this environment before?? */
/* we use the B field in the environment to tell whether we have
been here before or not
*/
2004-09-16 18:29:08 +01:00
if ( ! MARKED_PTR ( gc_ENV + E_CB ) )
2001-04-09 20:54:03 +01:00
return ;
UNMARK ( gc_ENV + E_CB ) ;
size = EnvSize ( ( CELL_PTR ) ( gc_ENV [ E_CP ] ) ) ; /* size = EnvSize(CP) */
pvbmap = EnvBMap ( ( CELL_PTR ) ( gc_ENV [ E_CP ] ) ) ;
gc_ENV = ( CELL_PTR ) gc_ENV [ E_E ] ; /* link to prev
* environment */
}
}
2002-05-14 19:24:34 +01:00
static void
sweep_slots ( CELL * ptr )
{
Int ns = IntOfTerm ( * ptr ) ;
ptr + + ;
while ( ns > 0 ) {
CELL cp_cell = * ptr ;
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( ptr ) ) {
2002-05-14 19:24:34 +01:00
UNMARK ( ptr ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( ptr , GET_NEXT ( cp_cell ) ) ;
}
}
ptr + + ;
ns - - ;
}
}
2004-09-27 21:45:04 +01:00
static void
sweep_b ( choiceptr gc_B , UInt arity )
{
register CELL_PTR saved_reg ;
sweep_environments ( gc_B - > cp_env ,
EnvSize ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ,
EnvBMap ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ) ;
/* for each saved register */
for ( saved_reg = & gc_B - > cp_a1 ;
saved_reg < & gc_B - > cp_a1 + arity ;
saved_reg + + ) {
CELL cp_cell = * saved_reg ;
if ( MARKED_PTR ( saved_reg ) ) {
UNMARK ( saved_reg ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( saved_reg , GET_NEXT ( cp_cell ) ) ;
}
}
}
}
2002-05-14 19:24:34 +01:00
2001-04-09 20:54:03 +01:00
/*
* insert cells of each choicepoint & its chain of environments which point
* to heap objects into relocation chains
*/
static void
sweep_choicepoints ( choiceptr gc_B )
{
2002-05-03 16:30:36 +01:00
# ifdef TABLING
dep_fr_ptr depfr = LOCAL_top_dep_fr ;
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2001-04-09 20:54:03 +01:00
while ( gc_B ! = NULL ) {
yamop * rtp = gc_B - > cp_ap ;
register OPCODE op ;
op_numbers opnum ;
# ifdef TABLING
2002-05-03 16:30:36 +01:00
/* include consumers */
if ( depfr ! = NULL & & gc_B > = DepFr_cons_cp ( depfr ) ) {
gc_B = DepFr_cons_cp ( depfr ) ;
depfr = DepFr_next ( depfr ) ;
2001-04-09 20:54:03 +01:00
continue ;
}
2002-05-03 16:30:36 +01:00
if ( rtp = = NULL ) {
opnum = _table_completion ;
} else
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2002-05-03 16:30:36 +01:00
{
op = rtp - > opc ;
2002-11-18 18:18:05 +00:00
opnum = Yap_op_from_opcode ( op ) ;
2002-05-03 16:30:36 +01:00
}
2001-04-09 20:54:03 +01:00
restart_cp :
/*
2002-11-18 18:18:05 +00:00
* fprintf ( Yap_stderr , " sweeping cps: %x, %x, %x \n " ,
2001-04-09 20:54:03 +01:00
* * gc_B , CP_Extra ( gc_B ) , CP_Nargs ( gc_B ) ) ;
*/
/* any choice point */
switch ( opnum ) {
case _Nstop :
/* end of the road, say bye bye! */
sweep_environments ( gc_B - > cp_env ,
EnvSizeInCells ,
NULL ) ;
2002-05-14 19:24:34 +01:00
sweep_slots ( gc_B - > cp_env ) ;
2001-04-09 20:54:03 +01:00
if ( gc_B - > cp_b ! = NULL ) {
break ;
} else
return ;
2002-01-22 15:06:22 +00:00
case _trust_fail :
sweep_environments ( gc_B - > cp_env ,
EnvSizeInCells ,
NULL ) ;
break ;
2001-04-09 20:54:03 +01:00
case _or_else :
case _or_last :
sweep_environments ( ( CELL_PTR ) ( gc_B - > cp_a1 ) ,
# ifdef YAPOR
- gc_B - > cp_cp - > u . ldl . s / ( ( OPREG ) sizeof ( CELL ) ) ,
2002-02-26 15:51:54 +00:00
( CELL * ) ( gc_B - > cp_cp - > u . ldl . bl )
2001-04-09 20:54:03 +01:00
# else
- gc_B - > cp_cp - > u . sla . s / ( ( OPREG ) sizeof ( CELL ) ) ,
2002-12-27 16:53:09 +00:00
gc_B - > cp_cp - > u . sla . bmap
2001-04-09 20:54:03 +01:00
# endif
) ;
break ;
case _trust_logical_pred :
case _retry_profiled :
2002-09-03 15:28:09 +01:00
case _count_retry :
2001-04-09 20:54:03 +01:00
rtp = NEXTOP ( rtp , l ) ;
op = rtp - > opc ;
2002-11-18 18:18:05 +00:00
opnum = Yap_op_from_opcode ( op ) ;
2001-04-09 20:54:03 +01:00
goto restart_cp ;
2003-04-30 18:46:05 +01:00
case _jump :
rtp = rtp - > u . l . l ;
op = rtp - > opc ;
opnum = Yap_op_from_opcode ( op ) ;
goto restart_cp ;
2001-04-09 20:54:03 +01:00
# ifdef TABLING
2005-08-01 16:40:39 +01:00
case _table_load_answer :
{
CELL * vars_ptr , vars ;
sweep_environments ( gc_B - > cp_env , EnvSize ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) , EnvBMap ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ) ;
vars_ptr = ( CELL * ) ( LOAD_CP ( gc_B ) + 1 ) ;
vars = * vars_ptr + + ;
while ( vars - - ) {
CELL cp_cell = * vars_ptr ;
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
}
}
vars_ptr + + ;
}
}
break ;
case _table_try_answer :
2005-07-06 20:34:12 +01:00
case _table_retry_me :
case _table_trust_me :
case _table_retry :
case _table_trust :
2001-04-09 20:54:03 +01:00
{
2005-07-06 20:34:12 +01:00
int nargs ;
CELL * vars_ptr , vars ;
sweep_environments ( gc_B - > cp_env , EnvSize ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) , EnvBMap ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ) ;
vars_ptr = ( CELL * ) ( GEN_CP ( gc_B ) + 1 ) ;
nargs = rtp - > u . ld . s ;
while ( nargs - - ) {
CELL cp_cell = * vars_ptr ;
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
}
}
vars_ptr + + ;
}
vars = * vars_ptr + + ;
2001-04-09 20:54:03 +01:00
while ( vars - - ) {
2005-07-06 20:34:12 +01:00
CELL cp_cell = * vars_ptr ;
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
2001-04-09 20:54:03 +01:00
if ( HEAP_PTR ( cp_cell ) ) {
2005-07-06 20:34:12 +01:00
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
2001-04-09 20:54:03 +01:00
}
}
2005-07-06 20:34:12 +01:00
vars_ptr + + ;
2001-04-09 20:54:03 +01:00
}
}
break ;
2005-07-06 20:34:12 +01:00
case _table_completion :
{
int nargs ;
CELL * vars_ptr , vars ;
sweep_environments ( gc_B - > cp_env , EnvSize ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) , EnvBMap ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ) ;
vars_ptr = ( CELL * ) ( GEN_CP ( gc_B ) + 1 ) ;
nargs = SgFr_arity ( GEN_CP ( gc_B ) - > cp_sg_fr ) ;
while ( nargs - - ) {
CELL cp_cell = * vars_ptr ;
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
2001-04-09 20:54:03 +01:00
}
}
2005-07-06 20:34:12 +01:00
vars_ptr + + ;
2001-04-09 20:54:03 +01:00
}
2005-07-06 20:34:12 +01:00
vars = * vars_ptr + + ;
while ( vars - - ) {
CELL cp_cell = * vars_ptr ;
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
}
}
vars_ptr + + ;
}
}
break ;
case _table_answer_resolution :
2001-04-09 20:54:03 +01:00
{
2005-07-06 20:34:12 +01:00
CELL * vars_ptr , vars ;
sweep_environments ( gc_B - > cp_env , EnvSize ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) , EnvBMap ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ) ;
init_substitution_pointer ( gc_B , vars_ptr , CONS_CP ( gc_B ) - > cp_dep_fr ) ;
vars = * vars_ptr + + ;
while ( vars - - ) {
CELL cp_cell = * vars_ptr ;
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
2001-04-09 20:54:03 +01:00
if ( HEAP_PTR ( cp_cell ) ) {
2005-07-06 20:34:12 +01:00
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
2001-04-09 20:54:03 +01:00
}
}
2005-07-06 20:34:12 +01:00
vars_ptr + + ;
2001-04-09 20:54:03 +01:00
}
}
break ;
2005-07-06 20:34:12 +01:00
case _trie_retry_null :
case _trie_trust_null :
case _trie_retry_var :
case _trie_trust_var :
case _trie_retry_val :
case _trie_trust_val :
case _trie_retry_atom :
case _trie_trust_atom :
case _trie_retry_list :
case _trie_trust_list :
case _trie_retry_struct :
case _trie_trust_struct :
case _trie_retry_extension :
case _trie_trust_extension :
case _trie_retry_float :
case _trie_trust_float :
case _trie_retry_long :
case _trie_trust_long :
{
CELL * vars_ptr ;
int heap_arity , vars_arity , subs_arity ;
sweep_environments ( gc_B - > cp_env , EnvSize ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) , EnvBMap ( ( CELL_PTR ) ( gc_B - > cp_cp ) ) ) ;
vars_ptr = ( CELL * ) ( gc_B + 1 ) ;
heap_arity = * vars_ptr ;
vars_arity = * ( vars_ptr + heap_arity + 1 ) ;
subs_arity = * ( vars_ptr + heap_arity + 2 ) ;
vars_ptr + = heap_arity + subs_arity + vars_arity + 2 ;
if ( vars_arity ) {
while ( vars_arity - - ) {
CELL cp_cell = * vars_ptr ;
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
2002-05-03 16:30:36 +01:00
}
}
2005-07-06 20:34:12 +01:00
vars_ptr - - ;
}
}
if ( subs_arity ) {
while ( subs_arity - - ) {
CELL cp_cell = * vars_ptr ;
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
2002-05-03 16:30:36 +01:00
}
}
2005-07-06 20:34:12 +01:00
vars_ptr - - ;
}
}
vars_ptr - = 2 ;
if ( heap_arity ) {
while ( heap_arity - - ) {
CELL cp_cell = * vars_ptr ;
if ( * vars_ptr = = 0 )
break ; /* term extension mark: float/longint */
if ( MARKED_PTR ( vars_ptr ) ) {
UNMARK ( vars_ptr ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( vars_ptr , GET_NEXT ( cp_cell ) ) ;
2002-05-03 16:30:36 +01:00
}
}
2005-07-06 20:34:12 +01:00
vars_ptr - - ;
2002-05-03 16:30:36 +01:00
}
}
2005-07-06 20:34:12 +01:00
}
break ;
# endif /* TABLING */
2004-09-27 21:45:04 +01:00
case _retry2 :
sweep_b ( gc_B , 2 ) ;
break ;
case _retry3 :
sweep_b ( gc_B , 3 ) ;
break ;
case _retry4 :
sweep_b ( gc_B , 4 ) ;
break ;
2001-04-09 20:54:03 +01:00
case _retry_c :
case _retry_userc :
{
register CELL_PTR saved_reg ;
/* for each extra saved register */
for ( saved_reg = & ( gc_B - > cp_a1 ) + rtp - > u . lds . s ;
saved_reg < & ( gc_B - > cp_a1 ) + rtp - > u . lds . s + rtp - > u . lds . extra ;
saved_reg + + ) {
CELL cp_cell = * saved_reg ;
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( saved_reg ) ) {
2001-04-09 20:54:03 +01:00
UNMARK ( saved_reg ) ;
if ( HEAP_PTR ( cp_cell ) ) {
into_relocation_chain ( saved_reg , GET_NEXT ( cp_cell ) ) ;
}
}
}
}
/* continue to clean environments and arguments */
default :
2004-09-27 21:45:04 +01:00
sweep_b ( gc_B , rtp - > u . ld . s ) ;
2001-04-09 20:54:03 +01:00
}
/* link to prev choicepoint */
gc_B = gc_B - > cp_b ;
}
}
/* update a relocation chain to point all its cells to new location of object */
static void
update_relocation_chain ( CELL_PTR current , CELL_PTR dest )
{
CELL_PTR next ;
CELL ccur = * current ;
2005-09-09 18:23:43 +01:00
# if GC_NO_TAGS
int rmarked = RMARKED ( current ) ;
2005-09-21 04:49:33 +01:00
UNRMARK ( current ) ;
2005-09-09 18:23:43 +01:00
while ( rmarked ) {
CELL current_tag ;
next = GET_NEXT ( ccur ) ;
current_tag = TAG ( ccur ) ;
ccur = * next ;
2005-09-21 04:49:33 +01:00
rmarked = RMARKED ( next ) ;
UNRMARK ( next ) ;
2005-09-09 18:23:43 +01:00
* next = ( CELL ) dest | current_tag ;
}
2005-09-21 04:49:33 +01:00
* current = ccur ;
2005-09-09 18:23:43 +01:00
# elif TAGS_FAST_OPS
2004-09-30 20:51:54 +01:00
while ( RMARKED ( current ) ) {
2001-04-09 20:54:03 +01:00
register CELL cnext ;
next = GET_NEXT ( ccur ) ;
cnext = * next ;
if ( IsVarTerm ( ccur ) ) {
ccur = * current = ( MARKED_VAR ( ccur ) ?
ENSURE_MARKED ( cnext ) :
UNMARKED ( cnext ) ) ;
* next = ( MARKED ( cnext ) ? MBIT : 0 ) | ( Int ) dest ;
} else if ( IsPairTerm ( ccur ) ) {
ccur = * current = ( MARKED_COMP ( ccur ) ?
ENSURE_MARKED ( cnext ) :
UNMARKED ( cnext ) ) ;
* next = AbsPair ( ( CELL * )
( ( MARKED ( cnext ) ? MBIT : 0 ) |
( Int ) dest ) ) ;
} else if ( IsApplTerm ( ccur ) ) {
ccur = * current = ( MARKED_COMP ( ccur ) ?
ENSURE_MARKED ( cnext ) :
UNMARKED ( cnext ) ) ;
* next = AbsAppl ( ( CELL * )
( ( MARKED ( cnext ) ? MBIT : 0 ) |
( Int ) dest ) ) ;
}
# ifdef DEBUG
else {
2002-11-18 18:18:05 +00:00
Yap_Error ( SYSTEM_ERROR , TermNil , " ATOMIC in a GC relocation chain " ) ;
2001-04-09 20:54:03 +01:00
}
# endif
}
2005-06-01 14:53:46 +01:00
# else /* !TAGS_FAST_OPS */
2004-09-30 20:51:54 +01:00
while ( RMARKED ( current ) ) {
2001-04-09 20:54:03 +01:00
CELL current_tag ;
next = GET_NEXT ( ccur ) ;
current_tag = TAG ( ccur ) ;
ccur = * current = ( ccur & MBIT ) | ( * next & ~ MBIT ) ;
# if INVERT_RBIT
* next = ( * next & MBIT ) | ( CELL ) dest | current_tag | RBIT ;
# else
* next = ( * next & MBIT ) | ( CELL ) dest | current_tag ;
# endif
}
2005-09-09 18:23:43 +01:00
# endif
2001-04-09 20:54:03 +01:00
}
2002-05-03 16:30:36 +01:00
# ifdef TABLING
static dep_fr_ptr gl_depfr ;
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2002-05-03 16:30:36 +01:00
2001-04-09 20:54:03 +01:00
static inline choiceptr
2002-05-03 16:30:36 +01:00
update_B_H ( choiceptr gc_B , CELL * current , CELL * dest , CELL * odest ) {
2001-04-09 20:54:03 +01:00
/* also make the value of H in a choicepoint
coherent with the new global
*/
while ( gc_B & & current < = gc_B - > cp_h ) {
if ( gc_B - > cp_h = = current ) {
gc_B - > cp_h = dest ;
} else {
gc_B - > cp_h = odest ;
}
gc_B = gc_B - > cp_b ;
2002-05-03 16:30:36 +01:00
# ifdef TABLING
if ( gl_depfr ! = NULL & & gc_B > = DepFr_cons_cp ( gl_depfr ) ) {
gc_B = DepFr_cons_cp ( gl_depfr ) ;
gl_depfr = DepFr_next ( gl_depfr ) ;
}
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2001-04-09 20:54:03 +01:00
}
2002-05-03 16:30:36 +01:00
return ( gc_B ) ;
2001-04-09 20:54:03 +01:00
}
2005-09-09 18:23:43 +01:00
static inline CELL *
set_next_hb ( choiceptr gc_B )
{
if ( gc_B ) {
return gc_B - > cp_h ;
} else {
return H0 ;
}
}
2001-04-09 20:54:03 +01:00
/*
* move marked objects on the heap upwards over unmarked objects , and reset
* all pointers to point to new locations
*/
static void
compact_heap ( void )
{
CELL_PTR dest , current , next ;
# ifdef DEBUG
Int found_marked = 0 ;
# endif /* DEBUG */
choiceptr gc_B = B ;
int in_garbage = 0 ;
2005-09-09 18:23:43 +01:00
CELL * next_hb ;
CELL * start_from = H0 ;
2001-04-09 20:54:03 +01:00
/*
* upward phase - scan heap from high to low , setting marked upward
* ptrs to point to what will be the new locations of the
* objects pointed to
*/
2005-09-09 18:23:43 +01:00
next_hb = set_next_hb ( gc_B ) ;
2002-05-03 16:30:36 +01:00
# ifdef TABLING
gl_depfr = LOCAL_top_dep_fr ;
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2001-04-09 20:54:03 +01:00
dest = ( CELL_PTR ) H0 + total_marked - 1 ;
2005-09-21 04:49:33 +01:00
2005-09-09 18:23:43 +01:00
for ( current = H - 1 ; current > = start_from ; current - - ) {
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( current ) ) {
2001-04-09 20:54:03 +01:00
CELL ccell = UNMARK_CELL ( * current ) ;
2004-10-04 19:56:20 +01:00
if (
2005-09-09 18:23:43 +01:00
IN_BETWEEN ( EndSpecials , ccell , MAX_SPECIALS_TAG ) /* two first pages */
& & IsVarTerm ( ccell )
2001-04-09 20:54:03 +01:00
) {
/* oops, we found a blob */
int nofcells = ( UNMARK_CELL ( * current ) - EndSpecials ) / sizeof ( CELL ) ;
CELL * ptr = current - nofcells ;
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( ptr ) ) {
2001-04-09 20:54:03 +01:00
# ifdef DEBUG
found_marked + = nofcells ;
# endif /* DEBUG */
2005-09-09 18:23:43 +01:00
if ( current < = next_hb ) {
gc_B = update_B_H ( gc_B , current , dest , dest + 1 ) ;
next_hb = set_next_hb ( gc_B ) ;
}
2001-04-09 20:54:03 +01:00
/* this one's being used */
/* first swap the tag so that it will be seen by the next step */
{
CELL tmp = current [ 0 ] ;
current [ 0 ] = ptr [ 1 ] ;
2004-09-30 20:51:54 +01:00
# if GC_NO_TAGS
MARK ( ptr + 1 ) ;
# endif
2001-04-09 20:54:03 +01:00
ptr [ 1 ] = tmp ;
}
if ( in_garbage > 0 ) {
current [ 1 ] = in_garbage ;
in_garbage = 0 ;
}
dest - = nofcells ;
current = ptr ;
/* process the functor next */
} else {
/* skip the term */
in_garbage + = nofcells + 1 ;
current = ptr ;
continue ;
}
} else {
2005-09-09 18:23:43 +01:00
if ( current < = next_hb ) {
gc_B = update_B_H ( gc_B , current , dest , dest + 1 ) ;
next_hb = set_next_hb ( gc_B ) ;
}
2001-04-09 20:54:03 +01:00
}
if ( in_garbage > 0 ) {
current [ 1 ] = in_garbage ;
in_garbage = 0 ;
}
# ifdef DEBUG
found_marked + + ;
# endif /* DEBUG */
update_relocation_chain ( current , dest ) ;
if ( HEAP_PTR ( * current ) ) {
next = GET_NEXT ( * current ) ;
if ( next < current ) /* push into reloc.
* chain */
into_relocation_chain ( current , next ) ;
2004-09-30 20:51:54 +01:00
else if ( current = = next ) { /* cell pointing to
2001-04-09 20:54:03 +01:00
* itself */
2004-09-30 20:51:54 +01:00
# if GC_NO_TAGS
UNRMARK ( current ) ;
* current = ( CELL ) dest ; /* no tag */
# else
2001-04-09 20:54:03 +01:00
* current = ( * current & MBIT ) | ( CELL ) dest ; /* no tag */
2004-09-30 20:51:54 +01:00
# endif
}
2001-04-09 20:54:03 +01:00
}
dest - - ;
} else {
in_garbage + + ;
}
}
if ( in_garbage )
2005-09-09 18:23:43 +01:00
start_from [ 0 ] = in_garbage ;
2001-04-09 20:54:03 +01:00
# ifdef DEBUG
if ( total_marked ! = found_marked )
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% Upward (%d): %ld total against %ld found \n " ,
2004-10-06 17:55:48 +01:00
GcCalls ,
2001-04-09 20:54:03 +01:00
( unsigned long int ) total_marked ,
( unsigned long int ) found_marked ) ;
2005-09-09 18:23:43 +01:00
found_marked = start_from - H0 ;
2001-04-09 20:54:03 +01:00
# endif
/*
* downward phase - scan heap from low to high , moving marked objects
* to their new locations & setting downward pointers to pt to new
* locations
*/
2005-09-09 18:23:43 +01:00
dest = ( CELL_PTR ) start_from ;
for ( current = start_from ; current < H ; current + + ) {
2001-04-09 20:54:03 +01:00
CELL ccur = * current ;
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( current ) ) {
2001-04-09 20:54:03 +01:00
CELL uccur = UNMARK_CELL ( ccur ) ;
2004-10-04 19:56:20 +01:00
if (
uccur < MAX_SPECIALS_TAG & & /* two first pages */
uccur > EndSpecials & & IsVarTerm ( uccur ) ) {
2001-04-09 20:54:03 +01:00
/* oops, we found a blob */
int nofcells = ( uccur - EndSpecials ) / sizeof ( CELL ) , i ;
* dest + + = current [ nofcells - 1 ] ;
current + + ;
for ( i = 0 ; i < nofcells - 2 ; i + + ) {
* dest + + = * current + + ;
}
* dest + + = ccur ;
# ifdef DEBUG
found_marked + = nofcells ;
# endif
continue ;
}
# ifdef DEBUG
found_marked + + ;
# endif
update_relocation_chain ( current , dest ) ;
ccur = * current ;
next = GET_NEXT ( ccur ) ;
2005-09-09 18:23:43 +01:00
if ( next < H & & /* move current cell &
2001-04-09 20:54:03 +01:00
* push */
next > current ) { /* into relocation chain */
* dest = ccur ;
into_relocation_chain ( dest , next ) ;
UNMARK ( dest ) ;
} else {
/* just move current cell */
* dest = ccur = UNMARK_CELL ( ccur ) ;
}
/* next cell, please */
dest + + ;
} else {
current + = ( ccur - 1 ) ;
}
}
# ifdef DEBUG
if ( total_marked ! = found_marked )
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% Downward (%d): %ld total against %ld found \n " ,
2004-10-06 17:55:48 +01:00
GcCalls ,
2001-04-09 20:54:03 +01:00
( unsigned long int ) total_marked ,
( unsigned long int ) found_marked ) ;
# endif
H = dest ; /* reset H */
HB = B - > cp_h ;
# ifdef TABLING
if ( B_FZ = = ( choiceptr ) LCL0 )
H_FZ = H0 ;
else
H_FZ = B_FZ - > cp_h ;
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2001-04-09 20:54:03 +01:00
}
2001-05-02 15:19:10 +01:00
# ifdef HYBRID_SCHEME
2001-05-07 20:56:02 +01:00
static void
adjust_cp_hbs ( void )
{
2002-05-03 16:30:36 +01:00
# ifdef TABLING
dep_fr_ptr depfr = LOCAL_top_dep_fr ;
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2001-05-07 20:56:02 +01:00
choiceptr gc_B = B ;
CELL_PTR * top = iptop - 1 , * base = ( CELL_PTR * ) H ;
while ( gc_B ! = NULL ) {
CELL * gc_H = gc_B - > cp_h ;
CELL_PTR * nbase = base ;
if ( top [ 0 ] < = gc_H ) {
if ( top [ 0 ] = = gc_H )
gc_B - > cp_h = H0 + ( top - base ) ;
else
gc_B - > cp_h = H0 + ( ( top + 1 ) - base ) ;
} else while ( TRUE ) {
CELL_PTR * nxt = nbase + ( top - nbase ) / 2 ;
if ( nxt [ 0 ] > gc_H ) {
2001-11-26 12:33:05 +00:00
if ( nbase = = top ) {
if ( nbase = = base ) {
gc_B - > cp_h = H0 ;
break ;
} else {
2002-11-18 18:18:05 +00:00
Yap_Error ( SYSTEM_ERROR , TermNil , " Bug in Garbage collector " ) ;
2001-11-26 12:33:05 +00:00
return ;
}
}
2001-05-07 20:56:02 +01:00
top = nxt ;
} else if ( nxt [ 0 ] < gc_H & & nxt [ 1 ] < gc_H ) {
nbase = nxt + 1 ;
} else {
if ( nxt [ 0 ] = = gc_H ) {
gc_B - > cp_h = H0 + ( nxt - base ) ;
top = nxt ;
break ;
} else {
gc_B - > cp_h = H0 + ( ( nxt - base ) + 1 ) ;
top = nxt ;
break ;
}
}
}
2002-05-03 16:30:36 +01:00
# ifdef TABLING
if ( depfr ! = NULL & & gc_B > = DepFr_cons_cp ( depfr ) ) {
gc_B = DepFr_cons_cp ( depfr ) ;
depfr = DepFr_next ( depfr ) ;
} else
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2002-05-03 16:30:36 +01:00
gc_B = gc_B - > cp_b ;
2001-05-07 20:56:02 +01:00
}
}
2001-05-02 15:19:10 +01:00
/*
* move marked objects on the heap upwards over unmarked objects , and reset
* all pointers to point to new locations
*/
static void
icompact_heap ( void )
{
CELL_PTR * iptr , * ibase = ( CELL_PTR * ) H ;
# ifdef DEBUG
Int found_marked = 0 ;
# endif /* DEBUG */
/*
* upward phase - scan heap from high to low , setting marked upward
* ptrs to point to what will be the new locations of the
* objects pointed to
*/
for ( iptr = iptop - 1 ; iptr > = ibase ; iptr - - ) {
CELL ccell ;
CELL_PTR current ;
current = * iptr ;
ccell = UNMARK_CELL ( * current ) ;
2004-10-04 19:56:20 +01:00
if ( ccell < MAX_SPECIALS_TAG & & /* two first pages */
ccell > EndSpecials & & IsVarTerm ( ccell )
2001-05-02 15:19:10 +01:00
) {
/* oops, we found a blob */
int nofcells = ( UNMARK_CELL ( * current ) - EndSpecials ) / sizeof ( CELL ) ;
CELL * ptr = current - nofcells ;
iptr - = nofcells ;
# ifdef DEBUG
found_marked + = nofcells ;
# endif /* DEBUG */
/* this one's being used */
/* first swap the tag so that it will be seen by the next step */
{
CELL tmp = current [ 0 ] ;
current [ 0 ] = ptr [ 1 ] ;
2004-09-30 20:51:54 +01:00
# if GC_NO_TAGS
MARK ( ptr + 1 ) ;
# endif
2001-05-02 15:19:10 +01:00
ptr [ 1 ] = tmp ;
}
current = ptr ;
}
# ifdef DEBUG
found_marked + + ;
# endif /* DEBUG */
update_relocation_chain ( current , H0 + ( iptr - ibase ) ) ;
if ( HEAP_PTR ( * current ) ) {
CELL_PTR next ;
next = GET_NEXT ( * current ) ;
if ( next < current ) /* push into reloc.
* chain */
into_relocation_chain ( current , next ) ;
2004-09-30 20:51:54 +01:00
else if ( current = = next ) { /* cell pointing to
* itself */
# if GC_NO_TAGS
* current = ( CELL ) ( H0 + ( iptr - ibase ) ) ; /* no tag */
# else
2001-05-02 15:19:10 +01:00
* current = ( * current & MBIT ) | ( CELL ) ( H0 + ( iptr - ibase ) ) ; /* no tag */
2004-09-30 20:51:54 +01:00
# endif
}
2001-05-02 15:19:10 +01:00
}
}
# ifdef DEBUG
if ( total_marked ! = found_marked )
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% Upward (%d): %ld total against %ld found \n " ,
2004-10-06 17:55:48 +01:00
GcCalls ,
2001-05-02 15:19:10 +01:00
( unsigned long int ) total_marked ,
( unsigned long int ) found_marked ) ;
found_marked = 0 ;
# endif
/*
* downward phase - scan heap from low to high , moving marked objects
* to their new locations & setting downward pointers to pt to new
* locations
*/
for ( iptr = ibase ; iptr < iptop ; iptr + + ) {
CELL_PTR next ;
CELL * current = * iptr ;
CELL ccur = * current ;
CELL_PTR dest = H0 + ( iptr - ibase ) ;
CELL uccur = UNMARK_CELL ( ccur ) ;
2004-10-04 19:56:20 +01:00
if ( uccur < MAX_SPECIALS_TAG & & uccur > EndSpecials & & IsVarTerm ( uccur ) ) {
2001-05-02 15:19:10 +01:00
/* oops, we found a blob */
int nofcells = ( uccur - EndSpecials ) / sizeof ( CELL ) , i ;
* dest + + = current [ nofcells - 1 ] ;
current + + ;
for ( i = 0 ; i < nofcells - 2 ; i + + ) {
* dest + + = * current + + ;
}
* dest = ccur ;
iptr + = nofcells - 1 ;
# ifdef DEBUG
found_marked + = nofcells ;
# endif
continue ;
}
# ifdef DEBUG
found_marked + + ;
# endif
update_relocation_chain ( current , dest ) ;
ccur = * current ;
next = GET_NEXT ( ccur ) ;
if ( HEAP_PTR ( ccur ) & & /* move current cell &
* push */
next > current ) { /* into relocation chain */
* dest = ccur ;
into_relocation_chain ( dest , next ) ;
UNMARK ( dest ) ;
} else {
/* just move current cell */
* dest = ccur = UNMARK_CELL ( ccur ) ;
}
}
# ifdef DEBUG
if ( total_marked ! = found_marked )
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% Downward (%d): %ld total against %ld found \n " ,
2004-10-06 17:55:48 +01:00
GcCalls ,
2001-05-02 15:19:10 +01:00
( unsigned long int ) total_marked ,
( unsigned long int ) found_marked ) ;
# endif
H = H0 + ( iptop - ibase ) ; /* reset H */
HB = B - > cp_h ;
# ifdef TABLING
if ( B_FZ = = ( choiceptr ) LCL0 )
H_FZ = H0 ;
else
H_FZ = B_FZ - > cp_h ;
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2001-05-02 15:19:10 +01:00
}
# endif /* HYBRID_SCHEME */
# ifdef EASY_SHUNTING
2001-04-26 15:44:43 +01:00
static void
2001-12-02 16:54:39 +00:00
set_conditionals ( tr_fr_ptr sTR ) {
while ( sTR ! = sTR0 ) {
CELL * cptr ;
2001-04-26 15:44:43 +01:00
sTR - = 2 ;
2001-12-02 16:54:39 +00:00
cptr = ( CELL * ) TrailTerm ( sTR + 1 ) ;
* cptr = TrailTerm ( sTR ) ;
2001-04-26 15:44:43 +01:00
}
}
# endif
2001-04-09 20:54:03 +01:00
/*
* mark all objects on the heap that are accessible from active registers ,
* the trail , environments , and choicepoints
*/
static void
marking_phase ( tr_fr_ptr old_TR , CELL * current_env , yamop * curp , CELL * max )
{
2001-05-02 15:19:10 +01:00
# ifdef EASY_SHUNTING
2001-04-09 20:54:03 +01:00
current_B = B ;
# endif
init_dbtable ( old_TR ) ;
2001-12-02 16:54:39 +00:00
# ifdef EASY_SHUNTING
sTR0 = ( tr_fr_ptr ) db_vec ;
2002-02-28 18:25:55 +00:00
sTR = ( tr_fr_ptr ) db_vec ;
# else
cont_top0 = ( cont * ) db_vec ;
2001-12-02 16:54:39 +00:00
# endif
2002-02-18 15:26:41 +00:00
cont_top = ( cont * ) db_vec ;
2001-04-09 20:54:03 +01:00
/* These two must be marked first so that our trail optimisation won't lose
values */
mark_regs ( old_TR ) ; /* active registers & trail */
# ifdef COROUTINING
mark_delays ( max ) ;
# endif
/* active environments */
mark_environments ( current_env , EnvSize ( curp ) , EnvBMap ( ( CELL * ) curp ) ) ;
2002-01-28 04:30:40 +00:00
mark_choicepoints ( B , old_TR , is_gc_very_verbose ( ) ) ; /* choicepoints, and environs */
2001-05-02 15:19:10 +01:00
# ifdef EASY_SHUNTING
2001-12-02 16:54:39 +00:00
set_conditionals ( sTR ) ;
2001-04-26 15:44:43 +01:00
# endif
2001-04-09 20:54:03 +01:00
}
2005-09-21 04:49:33 +01:00
static void
sweep_oldgen ( CELL * max , CELL * base )
{
CELL * ptr = base ;
long int nof = 0 ;
while ( ptr < max ) {
if ( MARKED_PTR ( ptr ) ) {
nof + + ;
UNMARK ( ptr ) ;
if ( HEAP_PTR ( * ptr ) ) {
into_relocation_chain ( ptr , GET_NEXT ( * ptr ) ) ;
}
}
ptr + + ;
}
/* fprintf(stderr,"found %d, %p-%p\n", nof, base, max); */
}
2001-04-09 20:54:03 +01:00
# ifdef COROUTINING
static void
sweep_delays ( CELL * max )
{
2002-11-18 18:18:05 +00:00
CELL * ptr = ( CELL * ) Yap_GlobalBase ;
2001-04-09 20:54:03 +01:00
while ( ptr < max ) {
2004-09-16 18:29:08 +01:00
if ( MARKED_PTR ( ptr ) ) {
2001-04-09 20:54:03 +01:00
UNMARK ( ptr ) ;
if ( HEAP_PTR ( * ptr ) ) {
into_relocation_chain ( ptr , GET_NEXT ( * ptr ) ) ;
}
}
ptr + + ;
}
}
# endif
/*
* move marked heap objects upwards over unmarked objects , and reset all
* pointers to point to new locations
*/
static void
compaction_phase ( tr_fr_ptr old_TR , CELL * current_env , yamop * curp , CELL * max )
{
2005-09-21 04:49:33 +01:00
CELL * CurrentH0 = NULL ;
int icompact = ( iptop < ( CELL_PTR * ) ASP & & 10 * total_marked < H - H0 ) ;
if ( icompact ) {
/* we are going to reuse the total space */
if ( HGEN ! = H0 ) {
/* undo optimisation */
total_marked + = total_oldies ;
}
} else {
if ( HGEN ! = H0 ) {
CurrentH0 = H0 ;
H0 = HGEN ;
sweep_oldgen ( HGEN , CurrentH0 ) ;
}
}
2001-04-09 20:54:03 +01:00
# ifdef COROUTINING
2001-05-02 15:19:10 +01:00
sweep_delays ( max ) ;
2001-04-09 20:54:03 +01:00
# endif
2001-05-02 15:19:10 +01:00
sweep_environments ( current_env , EnvSize ( curp ) , EnvBMap ( ( CELL * ) curp ) ) ;
sweep_choicepoints ( B ) ;
sweep_trail ( B , old_TR ) ;
# ifdef HYBRID_SCHEME
2005-09-21 04:49:33 +01:00
if ( icompact ) {
2001-05-02 15:19:10 +01:00
# ifdef DEBUG
2005-09-21 04:49:33 +01:00
if ( total_marked
2003-09-25 00:53:48 +01:00
# ifdef COROUTINING
2005-09-21 04:49:33 +01:00
- total_smarked
2003-09-25 00:53:48 +01:00
# endif
2005-09-21 04:49:33 +01:00
! = iptop - ( CELL_PTR * ) H & & iptop < ( CELL_PTR * ) ASP - 1024 )
fprintf ( Yap_stderr , " %% Oops on iptop-H (%ld) vs %ld \n " , ( unsigned long int ) ( iptop - ( CELL_PTR * ) H ) , total_marked ) ;
2001-05-02 15:19:10 +01:00
# endif
2005-09-21 04:49:33 +01:00
# if DEBUGX
2001-06-18 19:23:14 +01:00
int effectiveness = ( ( ( H - H0 ) - total_marked ) * 100 ) / ( H - H0 ) ;
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% using pointers (%d) \n " , effectiveness ) ;
2001-05-02 18:57:42 +01:00
# endif
2005-09-21 04:49:33 +01:00
if ( CurrentH0 ) {
H0 = CurrentH0 ;
HGEN = H0 ;
total_marked + = total_oldies ;
CurrentH0 = NULL ;
}
2001-05-02 18:57:42 +01:00
quicksort ( ( CELL_PTR * ) H , 0 , ( iptop - ( CELL_PTR * ) H ) - 1 ) ;
2001-05-07 20:56:02 +01:00
adjust_cp_hbs ( ) ;
2001-05-02 15:19:10 +01:00
icompact_heap ( ) ;
} else
# endif /* HYBRID_SCHEME */
2001-05-02 18:57:42 +01:00
{
2001-05-21 21:00:05 +01:00
# ifdef DEBUG
2004-09-30 20:51:54 +01:00
/*
# ifdef HYBRID_SCHEME
2001-05-02 18:57:42 +01:00
int effectiveness = ( ( ( H - H0 ) - total_marked ) * 100 ) / ( H - H0 ) ;
2004-09-03 04:11:09 +01:00
fprintf ( stderr , " %% not using pointers (%d) ASP: %p, ip %p (expected %p) \n " , effectiveness , ASP , iptop , H + total_marked ) ;
2004-09-30 20:51:54 +01:00
2001-05-21 21:00:05 +01:00
# endif
2004-09-30 20:51:54 +01:00
*/
2001-05-02 18:57:42 +01:00
# endif
compact_heap ( ) ;
}
2005-09-21 04:49:33 +01:00
if ( CurrentH0 ) {
H0 = CurrentH0 ;
}
2001-04-09 20:54:03 +01:00
}
static Int
do_gc ( Int predarity , CELL * current_env , yamop * nextop )
{
2004-10-27 16:56:34 +01:00
Int heap_cells ;
int gc_verbose ;
tr_fr_ptr old_TR = NULL ;
2004-03-02 16:44:58 +00:00
UInt m_time , c_time , time_start , gc_time ;
2004-10-27 16:56:34 +01:00
CELL * max ;
2005-09-21 04:49:33 +01:00
Int effectiveness , tot ;
2004-10-27 16:56:34 +01:00
int gc_trace ;
2001-04-09 20:54:03 +01:00
2004-10-27 16:56:34 +01:00
if ( setjmp ( Yap_gc_restore ) = = 2 ) {
/* we cannot recover, fail system */
Yap_Error ( OUT_OF_TRAIL_ERROR , TermNil , " could not expand trail during garbage collection " ) ;
}
heap_cells = H - H0 ;
gc_verbose = is_gc_verbose ( ) ;
effectiveness = 0 ;
gc_trace = FALSE ;
2002-04-11 02:43:09 +01:00
# if COROUTINING
2005-02-18 21:34:02 +00:00
max = ( CELL * ) DelayTop ( ) ;
while ( H0 - max < 1024 + ( 2 * NUM_OF_ATTS ) ) {
2002-11-18 18:18:05 +00:00
if ( ! Yap_growglobal ( & current_env ) ) {
2004-11-19 22:08:43 +00:00
Yap_Error ( OUT_OF_STACK_ERROR , TermNil , Yap_ErrorMessage ) ;
2004-02-05 16:57:02 +00:00
return 0 ;
2002-10-10 06:58:49 +01:00
}
2005-02-18 21:34:02 +00:00
max = ( CELL * ) DelayTop ( ) ;
2002-04-11 02:43:09 +01:00
}
2004-10-27 16:56:34 +01:00
# else
max = NULL ;
2002-04-11 02:43:09 +01:00
# endif
2001-04-09 20:54:03 +01:00
# ifdef INSTRUMENT_GC
{
int i ;
for ( i = 0 ; i < 16 ; i + + )
chain [ i ] = 0 ;
vars [ gc_var ] = 0 ;
vars [ gc_ref ] = 0 ;
vars [ gc_atom ] = 0 ;
vars [ gc_int ] = 0 ;
vars [ gc_num ] = 0 ;
vars [ gc_list ] = 0 ;
vars [ gc_appl ] = 0 ;
vars [ gc_func ] = 0 ;
vars [ gc_susp ] = 0 ;
env_vars = 0 ;
old_vars = new_vars = 0 ;
TrueHB = HB ;
num_bs = 0 ;
}
# endif
# ifdef DEBUG
2001-07-05 21:23:21 +01:00
check_global ( ) ;
2001-04-09 20:54:03 +01:00
# endif
2002-11-18 18:18:05 +00:00
if ( Yap_GetValue ( AtomGcTrace ) ! = TermNil )
2001-04-09 20:54:03 +01:00
gc_trace = 1 ;
2004-09-30 20:51:54 +01:00
# if !GC_NO_TAGS
2001-09-24 14:47:30 +01:00
/* sanity check: can we still do garbage_collection ? */
2002-11-18 18:18:05 +00:00
if ( ( CELL ) Yap_TrailTop & ( MBIT | RBIT ) ) {
2001-09-24 14:47:30 +01:00
/* oops, we can't */
if ( gc_verbose ) {
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% TrailTop at %p clashes with gc bits: %lx \n " , Yap_TrailTop , ( unsigned long int ) ( MBIT | RBIT ) ) ;
fprintf ( Yap_stderr , " %% garbage collection disallowed \n " ) ;
2001-09-24 14:47:30 +01:00
}
return ( 0 ) ;
}
2004-09-30 20:51:54 +01:00
# endif
2001-04-09 20:54:03 +01:00
if ( gc_trace ) {
2004-10-27 16:56:34 +01:00
fprintf ( Yap_stderr , " %% gc \n " ) ;
2001-04-09 20:54:03 +01:00
} else if ( gc_verbose ) {
2004-10-06 17:55:48 +01:00
fprintf ( Yap_stderr , " %% Start of garbage collection %d: \n " , GcCalls ) ;
2001-04-26 15:44:43 +01:00
# ifndef EARLY_RESET
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% no early reset in trail \n " ) ;
2001-04-26 15:44:43 +01:00
# endif
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% Global: %8ld cells (%p-%p) \n " , ( long int ) heap_cells , H0 , H ) ;
fprintf ( Yap_stderr , " %% Local:%8ld cells (%p-%p) \n " , ( unsigned long int ) ( LCL0 - ASP ) , LCL0 , ASP ) ;
fprintf ( Yap_stderr , " %% Trail:%8ld cells (%p-%p) \n " ,
2002-11-18 18:18:05 +00:00
( unsigned long int ) ( TR - ( tr_fr_ptr ) Yap_TrailBase ) , Yap_TrailBase , TR ) ;
2001-04-09 20:54:03 +01:00
}
2004-04-22 21:07:07 +01:00
# if !USE_SYSTEM_MALLOC
2002-11-18 18:18:05 +00:00
if ( HeapTop > = Yap_GlobalBase - MinHeapGap ) {
2001-06-27 13:46:35 +01:00
* - - ASP = ( CELL ) current_env ;
2004-01-23 02:23:51 +00:00
if ( ! Yap_growheap ( FALSE , MinHeapGap , NULL ) ) {
2004-11-19 22:08:43 +00:00
Yap_Error ( OUT_OF_HEAP_ERROR , TermNil , Yap_ErrorMessage ) ;
2005-02-24 21:46:40 +00:00
return FALSE ;
2001-06-27 13:46:35 +01:00
}
current_env = ( CELL * ) * ASP ;
ASP + + ;
2004-12-07 13:46:53 +00:00
# if COROUTINING
2005-02-18 21:34:02 +00:00
max = ( CELL * ) DelayTop ( ) ;
2004-12-07 13:46:53 +00:00
# endif
2001-06-27 13:46:35 +01:00
}
2004-04-22 21:07:07 +01:00
# endif
2002-11-18 18:18:05 +00:00
time_start = Yap_cputime ( ) ;
2001-04-09 20:54:03 +01:00
total_marked = 0 ;
2005-09-21 04:49:33 +01:00
total_oldies = 0 ;
2003-09-25 00:53:48 +01:00
# ifdef COROUTING
total_smarked = 0 ;
# endif
2001-04-09 20:54:03 +01:00
discard_trail_entries = 0 ;
2004-09-16 18:29:08 +01:00
# if GC_NO_TAGS
{
UInt alloc_sz = ( CELL * ) Yap_TrailTop - ( CELL * ) Yap_GlobalBase ;
bp = Yap_PreAllocCodeSpace ( ) ;
2005-01-05 04:32:18 +00:00
while ( bp + alloc_sz > ( char * ) AuxSp ) {
2004-09-16 18:29:08 +01:00
/* not enough space */
2004-09-30 20:51:54 +01:00
* - - ASP = ( CELL ) current_env ;
2004-12-05 05:01:45 +00:00
bp = ( char * ) Yap_ExpandPreAllocCodeSpace ( alloc_sz , NULL ) ;
2005-01-05 04:32:18 +00:00
if ( ! bp )
return 0 ;
2004-09-30 20:51:54 +01:00
current_env = ( CELL * ) * ASP ;
ASP + + ;
2004-12-07 13:46:53 +00:00
# if COROUTINING
2005-02-18 21:34:02 +00:00
max = ( CELL * ) DelayTop ( ) ;
2004-12-07 13:46:53 +00:00
# endif
2004-09-16 18:29:08 +01:00
}
2004-11-04 18:22:36 +00:00
memset ( ( void * ) bp , 0 , alloc_sz ) ;
2004-09-16 18:29:08 +01:00
}
# endif /* GC_NO_TAGS */
2001-06-27 13:46:35 +01:00
# ifdef HYBRID_SCHEME
iptop = ( CELL_PTR * ) H ;
# endif
2001-04-09 20:54:03 +01:00
/* get the number of active registers */
2005-09-21 04:49:33 +01:00
HGEN = H0 + IntegerOfTerm ( Yap_ReadTimedVar ( GcGeneration ) ) ;
2005-10-18 18:04:43 +01:00
/* old HGEN are not very reliable, but still may have data to recover */
if ( HGEN < HB ) {
choiceptr b_ptr = B ;
/* cannot trust the data between HGEN and its current choice-point */
while ( b_ptr ) {
if ( b_ptr - > cp_h < = HGEN ) {
HGEN = b_ptr - > cp_h ;
break ;
} else {
b_ptr = b_ptr - > cp_b ;
}
}
if ( ! b_ptr ) HGEN = H0 ;
}
2005-09-21 04:49:33 +01:00
/* fprintf(stderr,"HGEN is %ld, %p, %p/%p\n", IntegerOfTerm(Yap_ReadTimedVar(GcGeneration)), HGEN, H,H0);*/
2001-04-09 20:54:03 +01:00
YAPEnterCriticalSection ( ) ;
2005-01-04 02:50:23 +00:00
OldTR = ( tr_fr_ptr ) ( old_TR = TR ) ;
2001-04-09 20:54:03 +01:00
push_registers ( predarity , nextop ) ;
marking_phase ( old_TR , current_env , nextop , max ) ;
2005-09-21 04:49:33 +01:00
if ( total_oldies > ( ( HGEN - H0 ) * 8 ) / 10 ) {
total_marked - = total_oldies ;
tot = total_marked + ( HGEN - H0 ) ;
} else {
HGEN = H0 ;
tot = total_marked ;
}
2002-11-18 18:18:05 +00:00
m_time = Yap_cputime ( ) ;
2001-04-09 20:54:03 +01:00
gc_time = m_time - time_start ;
2004-09-16 18:29:08 +01:00
if ( heap_cells ) {
if ( heap_cells > 1000000 )
2005-09-21 04:49:33 +01:00
effectiveness = ( heap_cells - tot ) / ( heap_cells / 100 ) ;
2004-09-16 18:29:08 +01:00
else
2005-09-21 04:49:33 +01:00
effectiveness = 100 * ( heap_cells - tot ) / heap_cells ;
2004-09-16 18:29:08 +01:00
} else
2001-04-09 20:54:03 +01:00
effectiveness = 0 ;
if ( gc_verbose ) {
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% Mark: Recovered %ld cells of %ld (%ld%%) in %g sec \n " ,
2005-09-21 04:49:33 +01:00
( long int ) tot , ( long int ) heap_cells , ( long int ) effectiveness , ( double ) ( m_time - time_start ) / 1000 ) ;
if ( HGEN - H0 )
2005-10-18 18:04:43 +01:00
fprintf ( Yap_stderr , " %% previous generation has size %lu, with %lu (%lu%%) unmarked \n " , ( unsigned long ) ( HGEN - H0 ) , ( HGEN - H0 ) - total_oldies , 100 * ( ( HGEN - H0 ) - total_oldies ) / ( HGEN - H0 ) ) ;
2001-04-09 20:54:03 +01:00
# ifdef INSTRUMENT_GC
{
int i ;
for ( i = 0 ; i < 16 ; i + + ) {
if ( chain [ i ] ) {
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% chain[%d]=%lu \n " , i , chain [ i ] ) ;
2001-04-09 20:54:03 +01:00
}
}
2005-09-21 04:49:33 +01:00
put_type_info ( ( unsigned long int ) tot ) ;
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% %lu/%ld before and %lu/%ld after \n " , old_vars , ( unsigned long int ) ( B - > cp_h - H0 ) , new_vars , ( unsigned long int ) ( H - B - > cp_h ) ) ;
fprintf ( Yap_stderr , " %% %ld choicepoints \n " , num_bs ) ;
2001-04-09 20:54:03 +01:00
}
# endif
}
time_start = m_time ;
compaction_phase ( old_TR , current_env , nextop , max ) ;
TR = old_TR ;
pop_registers ( predarity , nextop ) ;
2001-05-21 21:00:05 +01:00
TR = new_TR ;
2001-04-09 20:54:03 +01:00
YAPLeaveCriticalSection ( ) ;
2005-09-21 04:49:33 +01:00
/* fprintf(Yap_stderr,"NEW HGEN %ld (%ld)\n", H-H0, HGEN-H0);*/
Yap_UpdateTimedVar ( GcGeneration , MkIntegerTerm ( H - H0 ) ) ;
2002-11-18 18:18:05 +00:00
c_time = Yap_cputime ( ) ;
2001-04-09 20:54:03 +01:00
if ( gc_verbose ) {
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% Compress: took %g sec \n " , ( double ) ( c_time - time_start ) / 1000 ) ;
2001-04-09 20:54:03 +01:00
}
gc_time + = ( c_time - time_start ) ;
2004-10-06 17:55:48 +01:00
TotGcTime + = gc_time ;
2005-09-21 04:49:33 +01:00
TotGcRecovered + = heap_cells - tot ;
2001-04-09 20:54:03 +01:00
if ( gc_verbose ) {
2004-10-06 17:55:48 +01:00
fprintf ( Yap_stderr , " %% GC %d took %g sec, total of %g sec doing GC so far. \n " , GcCalls , ( double ) gc_time / 1000 , ( double ) TotGcTime / 1000 ) ;
2004-09-03 04:11:09 +01:00
fprintf ( Yap_stderr , " %% Left %ld cells free in stacks. \n " ,
2001-04-09 20:54:03 +01:00
( unsigned long int ) ( ASP - H ) ) ;
}
2001-07-05 21:23:21 +01:00
check_global ( ) ;
2004-02-12 17:09:17 +00:00
return effectiveness ;
2001-04-09 20:54:03 +01:00
}
2002-11-11 17:38:10 +00:00
static int
2001-04-09 20:54:03 +01:00
is_gc_verbose ( void )
{
2001-05-21 21:00:05 +01:00
# ifdef INSTRUMENT_GC
/* always give info when we are debugging gc */
return ( TRUE ) ;
# else
2002-11-18 18:18:05 +00:00
return ( Yap_GetValue ( AtomGcVerbose ) ! = TermNil | |
Yap_GetValue ( AtomGcVeryVerbose ) ! = TermNil ) ;
2001-05-21 21:00:05 +01:00
# endif
2001-04-09 20:54:03 +01:00
}
2002-11-11 17:38:10 +00:00
int
2002-11-18 18:18:05 +00:00
Yap_is_gc_verbose ( void )
2002-11-11 17:38:10 +00:00
{
return is_gc_verbose ( ) ;
}
2002-01-28 04:30:40 +00:00
static int
is_gc_very_verbose ( void )
{
2002-11-18 18:18:05 +00:00
return ( Yap_GetValue ( AtomGcVeryVerbose ) ! = TermNil ) ;
2002-01-28 04:30:40 +00:00
}
2002-11-11 17:38:10 +00:00
Int
2002-11-18 18:18:05 +00:00
Yap_total_gc_time ( void )
2001-04-09 20:54:03 +01:00
{
2004-10-06 17:55:48 +01:00
return ( TotGcTime ) ;
2001-04-09 20:54:03 +01:00
}
static Int
p_inform_gc ( void )
{
2004-10-06 17:55:48 +01:00
Term tn = MkIntegerTerm ( TotGcTime ) ;
Term tt = MkIntegerTerm ( GcCalls ) ;
2004-10-06 20:40:22 +01:00
Term ts = MkIntegerTerm ( ( TotGcRecovered * sizeof ( CELL ) ) ) ;
2001-04-09 20:54:03 +01:00
2002-11-18 18:18:05 +00:00
return ( Yap_unify ( tn , ARG2 ) & & Yap_unify ( tt , ARG1 ) & & Yap_unify ( ts , ARG3 ) ) ;
2001-04-09 20:54:03 +01:00
}
2005-10-28 18:38:50 +01:00
int vsc_gc_calls ;
2003-05-19 14:04:09 +01:00
static int
call_gc ( UInt gc_lim , Int predarity , CELL * current_env , yamop * nextop )
2001-04-09 20:54:03 +01:00
{
2004-06-29 20:04:46 +01:00
UInt gc_margin = MinStackGap ;
2003-05-19 14:04:09 +01:00
Term Tgc_margin ;
Int effectiveness = 0 ;
int gc_on = FALSE ;
2001-04-09 20:54:03 +01:00
2002-10-21 23:52:36 +01:00
# if defined(YAPOR) || defined(THREADS)
if ( NOfThreads ! = 1 ) {
2002-11-18 18:18:05 +00:00
Yap_Error ( SYSTEM_ERROR , TermNil , " cannot perform garbage collection: more than a worker/thread running " ) ;
2002-10-21 23:52:36 +01:00
return ( FALSE ) ;
}
# endif
2002-11-18 18:18:05 +00:00
if ( Yap_GetValue ( AtomGc ) ! = TermNil )
2001-04-09 20:54:03 +01:00
gc_on = TRUE ;
2003-05-19 14:04:09 +01:00
if ( IsIntegerTerm ( Tgc_margin = Yap_GetValue ( AtomGcMargin ) ) & &
gc_margin > 0 ) {
gc_margin = ( UInt ) IntegerOfTerm ( Tgc_margin ) ;
2003-02-11 16:33:24 +00:00
} else {
2003-05-19 14:04:09 +01:00
/* only go exponential for the first 8 calls */
2004-10-06 17:55:48 +01:00
if ( GcCalls < 8 )
gc_margin < < = GcCalls ;
2003-05-19 14:04:09 +01:00
else {
/* next grow linearly */
2005-01-05 05:22:40 +00:00
gc_margin < < = 8 ;
2005-01-05 17:08:28 +00:00
/* don't do this: it forces the system to ask for ever more stack!!
2005-01-05 05:22:40 +00:00
gc_margin * = GcCalls ;
*/
2003-05-19 14:04:09 +01:00
}
2001-04-09 20:54:03 +01:00
}
2003-05-19 14:04:09 +01:00
if ( gc_margin < gc_lim )
gc_margin = gc_lim ;
2004-10-06 17:55:48 +01:00
GcCalls + + ;
2005-10-28 18:38:50 +01:00
vsc_gc_calls = GcCalls ;
2005-02-24 21:46:40 +00:00
if ( gc_on & & ! ( Yap_PrologMode & InErrorMode ) ) {
2001-04-09 20:54:03 +01:00
effectiveness = do_gc ( predarity , current_env , nextop ) ;
2003-05-19 14:04:09 +01:00
if ( effectiveness > 90 ) {
while ( gc_margin < H - H0 )
gc_margin < < = 1 ;
}
} else {
effectiveness = 0 ;
2001-05-02 18:57:42 +01:00
}
2001-09-24 14:47:30 +01:00
/* expand the stack if effectiveness is less than 20 % */
2004-02-12 17:09:17 +00:00
if ( ASP - H < gc_margin / sizeof ( CELL ) | |
2003-05-19 14:04:09 +01:00
effectiveness < 20 ) {
2004-08-11 17:14:55 +01:00
return Yap_growstack ( gc_margin ) ;
2001-04-09 20:54:03 +01:00
}
/*
* debug for ( save_total = 1 ; save_total < = N ; + + save_total )
2002-11-18 18:18:05 +00:00
* plwrite ( XREGS [ save_total ] , Yap_DebugPutc , 0 ) ;
2001-04-09 20:54:03 +01:00
*/
2004-12-07 06:01:55 +00:00
return TRUE ;
2001-04-09 20:54:03 +01:00
}
2003-05-19 14:04:09 +01:00
int
Yap_gc ( Int predarity , CELL * current_env , yamop * nextop )
{
2004-06-29 20:04:46 +01:00
int res ;
Yap_PrologMode | = GCMode ;
res = call_gc ( 4096 , predarity , current_env , nextop ) ;
Yap_PrologMode & = ~ GCMode ;
return res ;
2003-05-19 14:04:09 +01:00
}
int
Yap_gcl ( UInt gc_lim , Int predarity , CELL * current_env , yamop * nextop )
{
2004-02-12 17:09:17 +00:00
return call_gc ( gc_lim + CalculateStackGap ( ) * sizeof ( CELL ) , predarity , current_env , nextop ) ;
2003-05-19 14:04:09 +01:00
}
2001-04-09 20:54:03 +01:00
static Int
p_gc ( void )
{
2002-06-04 01:46:32 +01:00
do_gc ( 0 , ENV , P ) ;
2001-04-09 20:54:03 +01:00
return ( TRUE ) ;
}
void
2002-11-18 18:18:05 +00:00
Yap_init_gc ( void )
2001-04-09 20:54:03 +01:00
{
2004-11-18 22:32:40 +00:00
Yap_InitCPred ( " $gc " , 0 , p_gc , HiddenPredFlag ) ;
Yap_InitCPred ( " $inform_gc " , 3 , p_inform_gc , HiddenPredFlag ) ;
2002-11-11 17:38:10 +00:00
}
void
2002-11-18 18:18:05 +00:00
Yap_inc_mark_variable ( )
2002-11-11 17:38:10 +00:00
{
total_marked + + ;
2001-04-09 20:54:03 +01:00
}