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-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 */
2005-12-03 03:03:18 +00:00
STATIC_PROTO ( Int p_inform_gc , ( void ) ) ;
STATIC_PROTO ( Int p_gc , ( void ) ) ;
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 ( 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 ) ) ;
2007-10-18 09:24:16 +01:00
STATIC_PROTO ( void LeaveGCMode , ( void ) ) ;
2007-04-26 15:13:21 +01:00
# ifdef EASY_SHUNTING
2007-03-21 23:23:46 +00:00
STATIC_PROTO ( void set_conditionals , ( tr_fr_ptr ) ) ;
2007-04-26 15:13:21 +01:00
# endif /* EASY_SHUNTING */
2001-04-09 20:54:03 +01:00
# include "heapgc.h"
2005-12-07 17:53:30 +00:00
typedef struct gc_mark_continuation {
2001-06-27 13:46:35 +01:00
CELL * v ;
int nof ;
} cont ;
2005-12-07 17:53:30 +00:00
/* straightforward binary tree scheme that, given a key, finds a
matching dbref */
typedef enum {
db_entry ,
cl_entry ,
lcl_entry ,
li_entry ,
dcl_entry
} db_entry_type ;
typedef struct db_entry {
CODEADDR val ;
db_entry_type db_type ;
int in_use ;
struct db_entry * left ;
CODEADDR lim ;
struct db_entry * right ;
} * dbentry ;
typedef struct RB_red_blk_node {
CODEADDR key ;
CODEADDR lim ;
db_entry_type db_type ;
int in_use ;
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-12-02 16:54:39 +00:00
# ifdef EASY_SHUNTING
2005-12-07 17:53:30 +00:00
# undef cont_top0
2001-12-02 16:54:39 +00:00
# define cont_top0 (cont *)sTR
2005-12-07 17:53:30 +00:00
# endif
# if !defined(YAPOR) && !defined(THREADS)
/* in a single gc */
static unsigned long int total_marked , total_oldies ; /* number of heap objects marked */
# ifdef EASY_SHUNTING
static choiceptr current_B ;
static tr_fr_ptr sTR , sTR0 ;
static CELL * prev_HB ;
# endif
static tr_fr_ptr new_TR ;
static CELL * HGEN ;
char * Yap_bp ;
static int discard_trail_entries = 0 ;
# ifdef HYBRID_SCHEME
static CELL_PTR * iptop ;
# endif
# ifndef EASY_SHUNTING
2001-12-02 16:54:39 +00:00
static cont * cont_top0 ;
# endif
static cont * cont_top ;
2001-06-27 13:46:35 +01:00
2005-12-07 17:53:30 +00:00
static gc_ma_hash_entry gc_ma_hash_table [ GC_MAVARS_HASH_SIZE ] ;
2006-12-29 01:57:50 +00:00
static gc_ma_hash_entry * gc_ma_h_top , * gc_ma_h_list ;
2005-12-07 17:53:30 +00:00
static UInt gc_timestamp ; /* an unsigned int */
static ADDR db_vec , db_vec0 ;
static rb_red_blk_node * db_root , * db_nil ;
# endif /* !defined(YAPOR) && !defined(THREADS) */
/* support for hybrid garbage collection scheme */
2004-10-28 21:12:23 +01:00
static void
2007-03-21 18:32:50 +00:00
gc_growtrail ( int committed , tr_fr_ptr begsTR , cont * old_cont_top0 )
2004-10-27 16:56:34 +01:00
{
2007-03-21 18:32:50 +00:00
UInt sz = Yap_TrailTop - ( ADDR ) OldTR ;
/* ask for double the size */
sz = 2 * sz ;
if ( ! Yap_growtrail ( sz , TRUE ) ) {
# ifdef EASY_SHUNTING
if ( begsTR ) {
sTR = ( tr_fr_ptr ) old_cont_top0 ;
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 ;
}
}
2007-03-21 23:49:41 +00:00
set_conditionals ( sTR ) ;
2007-03-21 18:32:50 +00:00
# endif
2004-10-27 16:56:34 +01:00
/* could not find more trail */
2006-01-02 02:16:19 +00:00
save_machine_regs ( ) ;
2004-10-27 16:56:34 +01:00
longjmp ( Yap_gc_restore , 2 ) ;
}
}
2001-06-27 13:46:35 +01:00
inline static void
PUSH_CONTINUATION ( CELL * v , int nof ) {
cont * x ;
x = cont_top ;
x + + ;
2004-10-27 16:56:34 +01:00
if ( ( ADDR ) x > Yap_TrailTop - 1024 ) {
2007-03-21 18:32:50 +00:00
gc_growtrail ( TRUE , NULL , NULL ) ;
2004-10-27 16:56:34 +01:00
}
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
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
2005-11-07 15:35:47 +00:00
POPSWAP_POINTER ( CELL_PTR * vp , CELL_PTR v ) {
2001-05-02 15:19:10 +01:00
if ( iptop > = ( CELL_PTR * ) ASP ) return ;
2005-11-07 15:35:47 +00:00
if ( * vp ! = v )
return ;
2001-05-02 15:19:10 +01:00
- - 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 .
*/
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
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 )
2007-03-21 18:32:50 +00:00
gc_growtrail ( FALSE , NULL , NULL ) ;
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 ;
2006-12-29 01:57:50 +00:00
# if TABLING
gc_ma_hash_table [ i ] . loc = trp ;
gc_ma_hash_table [ i ] . more = gc_ma_h_list ;
gc_ma_h_list = gc_ma_hash_table + i ;
# endif
2004-04-16 21:38:54 +01:00
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 ) {
2006-12-29 01:57:50 +00:00
# if TABLING
/*
we ' re moving from oldest to more recent , so only a new entry
has the correct new value
*/
TrailVal ( nptr - > loc + 1 ) = TrailVal ( trp + 1 ) ;
# endif
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 ;
2006-12-29 01:57:50 +00:00
# if TABLING
nptr - > loc = trp ;
2006-12-29 10:26:27 +00:00
nptr - > more = gc_ma_h_list ;
2006-12-29 01:57:50 +00:00
# endif
2001-07-04 17:48:54 +01:00
nptr - > next = NULL ;
2006-12-29 01:57:50 +00:00
gc_ma_h_list = nptr ;
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 ;
2006-12-29 01:57:50 +00:00
gc_ma_h_list = NULL ;
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 */
2007-09-28 14:10:46 +01:00
static void
check_pr_trail ( tr_fr_ptr trp )
{
if ( ( tr_fr_ptr ) Yap_TrailTop - TR < 1024 ) {
if ( ! Yap_growtrail ( 0 , TRUE ) | | TRUE ) {
/* could not find more trail */
save_machine_regs ( ) ;
longjmp ( Yap_gc_restore , 2 ) ;
}
}
}
2001-04-09 20:54:03 +01:00
/* 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 ;
2006-08-22 17:12:46 +01:00
GlobalEntry * gl = GlobalVariables ;
TrailTerm ( TR + + ) = GlobalArena ;
TrailTerm ( TR + + ) = GlobalDelayArena ;
2005-10-28 18:38:50 +01:00
while ( al ) {
2007-09-28 14:10:46 +01:00
check_pr_trail ( TR ) ;
2005-10-28 18:38:50 +01:00
TrailTerm ( TR + + ) = al - > ValueOfVE ;
al = al - > NextAE ;
}
2006-08-22 17:12:46 +01:00
while ( gl ) {
2007-09-28 14:10:46 +01:00
check_pr_trail ( TR ) ;
2006-08-22 17:12:46 +01:00
TrailTerm ( TR + + ) = gl - > global ;
gl = gl - > NextGE ;
}
2005-10-28 18:38:50 +01:00
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 ) ) {
2007-09-28 14:10:46 +01:00
check_pr_trail ( TR ) ;
2006-03-30 02:11:10 +01:00
TrailTerm ( TR + + ) = tlive ;
2005-10-28 18:38:50 +01:00
}
}
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
}
2007-09-28 14:10:46 +01:00
check_pr_trail ( TR ) ;
2005-09-21 04:49:33 +01:00
TrailTerm ( TR ) = GcGeneration ;
TR + + ;
2006-03-06 14:04:57 +00:00
TrailTerm ( TR ) = GcPhase ;
TR + + ;
2001-04-09 20:54:03 +01:00
# ifdef COROUTINING
TrailTerm ( TR ) = WokenGoals ;
2005-12-05 17:16:12 +00:00
TrailTerm ( TR + 1 ) = AttsMutableList ;
TrailTerm ( TR + 2 ) = DelayedVars ;
TR + = 3 ;
2001-04-09 20:54:03 +01:00
# endif
2007-09-28 14:10:46 +01:00
for ( i = 1 ; i < = num_regs ; i + + ) {
check_pr_trail ( TR ) ;
2001-04-09 20:54:03 +01:00
TrailTerm ( TR + + ) = ( CELL ) XREGS [ i ] ;
2007-09-28 14:10:46 +01:00
}
2001-04-09 20:54:03 +01:00
/* 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 ) {
2007-09-28 14:10:46 +01:00
check_pr_trail ( TR ) ;
2001-04-09 20:54:03 +01:00
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 ;
2006-08-22 17:12:46 +01:00
GlobalEntry * gl = GlobalVariables ;
GlobalArena = TrailTerm ( ptr + + ) ;
GlobalDelayArena = TrailTerm ( ptr + + ) ;
2005-10-28 18:38:50 +01:00
while ( al ) {
al - > ValueOfVE = TrailTerm ( ptr + + ) ;
al = al - > NextAE ;
}
2006-08-22 17:12:46 +01:00
while ( gl ) {
gl - > global = TrailTerm ( ptr + + ) ;
gl = gl - > NextGE ;
}
2005-10-28 18:38:50 +01:00
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 + + ) ;
2006-03-06 14:04:57 +00:00
GcPhase = TrailTerm ( ptr + + ) ;
2001-04-09 20:54:03 +01:00
# ifdef COROUTINING
# ifdef MULTI_ASSIGNMENT_VARIABLES
WokenGoals = 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
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 ) {
2007-03-21 18:32:50 +00:00
gc_growtrail ( FALSE , NULL , NULL ) ;
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 ;
}
2006-08-07 19:51:44 +01:00
/* This is code originally written by Emin Martinian */
2004-09-16 18:29:08 +01:00
/***********************************************************************/
/* 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 ;
2005-12-07 12:55:31 +00:00
x - > in_use = FALSE ;
2004-09-16 18:29:08 +01:00
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 ) {
2006-02-14 17:20:49 +00:00
if ( current - > key < = entry & & current - > lim > entry ) {
2004-09-16 18:29:08 +01:00
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
}
2005-12-07 12:55:31 +00:00
/* find an element in the dbentries table */
static void
mark_ref_in_use ( DBRef ref )
{
rb_red_blk_node * el = find_ref_in_dbtable ( ( CODEADDR ) ref ) ;
el - > in_use = TRUE ;
}
static int
ref_in_use ( DBRef ref )
{
rb_red_blk_node * el = find_ref_in_dbtable ( ( CODEADDR ) ref ) ;
return el - > in_use ;
}
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 ) {
2005-12-07 12:55:31 +00:00
el - > in_use = TRUE ;
2003-04-30 18:46:05 +01:00
}
2001-04-09 20:54:03 +01:00
}
static void
init_dbtable ( tr_fr_ptr trail_ptr ) {
2006-03-22 20:07:28 +00:00
StaticClause * sc = DeadStaticClauses ;
MegaClause * mc = DeadMegaClauses ;
StaticIndex * si = DeadStaticIndices ;
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
2008-01-23 17:57:56 +00:00
( ADDR ) pt0 > = Yap_TrailBase & & ( ADDR ) pt0 < Yap_TrailTop
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
}
}
}
2006-03-22 20:07:28 +00:00
while ( sc ) {
store_in_dbtable ( ( CODEADDR ) sc , ( CODEADDR ) sc + sc - > ClSize , dcl_entry ) ;
sc = sc - > ClNext ;
}
while ( si ) {
store_in_dbtable ( ( CODEADDR ) si , ( CODEADDR ) si + si - > ClSize , dcl_entry ) ;
si = si - > SiblingIndex ;
}
while ( mc ) {
store_in_dbtable ( ( CODEADDR ) mc , ( CODEADDR ) mc + mc - > ClSize , dcl_entry ) ;
mc = mc - > ClNext ;
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 ) ;
2006-08-22 17:12:46 +01:00
if ( ccell = = EndSpecials ) {
2001-04-09 20:54:03 +01:00
/* oops, we found a blob */
2006-08-22 17:12:46 +01:00
CELL * ptr = current - 1 ;
UInt nofcells ;
while ( ! MARKED_PTR ( ptr ) ) ptr - - ;
nofcells = current - ptr ;
2001-04-09 20:54:03 +01:00
current = ptr ;
ccurr = * current ;
/* process the functor next */
}
}
# 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 ;
2006-08-05 04:06:31 +01:00
char * local_bp = Yap_bp ;
2001-04-09 20:54:03 +01:00
begin :
2006-08-05 04:06:31 +01:00
if ( UNMARKED_MARK ( current , local_bp ) ) {
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
}
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
UNMARK ( next ) ;
MARK ( current ) ;
* current = ( CELL ) current ;
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
UNMARK ( current ) ;
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
UNMARK ( 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
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 ( ) ;
2006-08-05 04:06:31 +01:00
} else if ( IsAtomOrIntTerm ( ccur ) ) {
# ifdef INSTRUMENT_GC
if ( IsAtomTerm ( ccur ) )
inc_vars_of_type ( current , gc_atom ) ;
else
inc_vars_of_type ( current , gc_int ) ;
# endif
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 ) ) {
2006-08-05 04:06:31 +01:00
/* speedup for strings */
if ( IsAtomOrIntTerm ( * next ) ) {
if ( ! UNMARKED_MARK ( next , local_bp ) ) {
total_marked + + ;
if ( next < HGEN ) {
total_oldies + + ;
}
PUSH_POINTER ( next ) ;
}
current = next + 1 ;
goto begin ;
} else {
PUSH_CONTINUATION ( next + 1 , 1 ) ;
current = next ;
goto begin ;
}
2001-04-09 20:54:03 +01:00
} 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 ) ;
2006-02-24 14:03:42 +00:00
2001-04-09 20:54:03 +01:00
/* make sure the reference is marked as in use */
2006-02-24 14:03:42 +00:00
if ( ( tref - > Flags & ( ErasedMask | LogUpdMask ) ) = = ( ErasedMask | LogUpdMask ) ) {
* current = MkDBRefTerm ( ( DBRef ) LogDBErasedMarker ) ;
2002-06-12 17:48:35 +01:00
MARK ( current ) ;
} else {
2005-12-07 12:55:31 +00:00
mark_ref_in_use ( tref ) ;
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
MARK ( next + 2 ) ;
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 + 2 ) ;
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
case ( CELL ) FunctorDouble :
MARK ( next ) ;
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( next ) ;
2006-08-22 17:12:46 +01:00
{
UInt sz = 1 + SIZEOF_DOUBLE / SIZEOF_LONG_INT ;
if ( next < HGEN ) {
total_oldies + = 1 + sz ;
}
total_marked + = 1 + sz ;
PUSH_POINTER ( next + sz ) ;
MARK ( next + sz ) ;
}
2001-06-27 13:46:35 +01:00
POP_CONTINUATION ( ) ;
2001-04-09 20:54:03 +01:00
case ( CELL ) FunctorBigInt :
2001-05-02 15:19:10 +01:00
{
2006-08-22 17:12:46 +01:00
UInt sz = ( sizeof ( MP_INT ) +
2008-01-23 17:57:56 +00:00
( ( MP_INT * ) ( next + 1 ) ) - > _mp_alloc * sizeof ( mp_limb_t ) ) / CellSize ;
2006-08-22 17:12:46 +01:00
MARK ( next ) ;
/* size is given by functor + friends */
if ( next < HGEN )
total_oldies + = 2 + sz ;
total_marked + = 2 + sz ;
2001-05-02 15:19:10 +01:00
PUSH_POINTER ( next ) ;
2006-08-22 17:12:46 +01:00
sz + + ;
MARK ( next + sz ) ;
PUSH_POINTER ( next + sz ) ;
2001-05-02 15:19:10 +01:00
}
2001-04-09 20:54:03 +01:00
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 ) ;
2006-09-01 21:14:42 +01:00
next + + ;
/* speedup for leaves */
while ( arity & & IsAtomOrIntTerm ( * next ) ) {
if ( ! UNMARKED_MARK ( next , local_bp ) ) {
total_marked + + ;
if ( next < HGEN ) {
total_oldies + + ;
}
PUSH_POINTER ( next ) ;
}
next + + ;
arity - - ;
}
if ( ! arity ) POP_CONTINUATION ( ) ;
current = next ;
if ( arity = = 1 ) goto begin ;
2001-06-27 13:46:35 +01:00
PUSH_CONTINUATION ( current + 1 , arity - 1 ) ;
2001-04-09 20:54:03 +01:00
goto begin ;
}
}
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 */
2006-02-24 14:03:42 +00:00
if ( ( tref - > Flags & ( LogUpdMask | ErasedMask ) ) = = ( LogUpdMask | ErasedMask ) ) {
* ptr = MkDBRefTerm ( ( DBRef ) LogDBErasedMarker ) ;
2005-09-09 18:23:43 +01:00
} else {
2005-12-07 12:55:31 +00:00
mark_ref_in_use ( tref ) ;
2005-09-09 18:23:43 +01:00
}
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 ) ;
2005-11-07 15:35:47 +00:00
POPSWAP_POINTER ( old , ptr ) ;
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 ) ;
2005-11-07 15:35:47 +00:00
POPSWAP_POINTER ( old , ptr ) ;
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 ? */
2007-05-14 17:44:12 +01:00
for ( trail_ptr = old_TR ; trail_ptr < TR ; trail_ptr + + ) {
2001-04-09 20:54:03 +01:00
mark_external_reference ( & TrailTerm ( trail_ptr ) ) ;
2007-05-14 17:44:12 +01:00
}
2001-04-09 20:54:03 +01:00
}
/* 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 ) ;
}
2006-08-30 02:06:30 +01:00
2001-04-09 20:54:03 +01:00
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 ) ;
2008-06-17 14:37:51 +01:00
2008-08-28 04:43:00 +01:00
size = EnvSize ( ( yamop * ) ( gc_ENV [ E_CP ] ) ) ; /* size = EnvSize(CP) */
pvbmap = EnvBMap ( ( yamop * ) ( 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 .
*/
2008-08-28 17:41:07 +01:00
static void
mark_att_var ( CELL * hp )
{
2008-11-13 09:03:27 +00:00
attvar_record * top = ( attvar_record * ) Yap_GlobalBase ;
int relpos = top - ( attvar_record * ) hp ;
attvar_record * attv = top - relpos ;
if ( attv ! = ( attvar_record * ) hp )
attv - - ;
2008-08-28 17:41:07 +01:00
mark_external_reference2 ( & attv - > Done ) ;
mark_external_reference2 ( & attv - > Value ) ;
mark_external_reference2 ( & attv - > Atts ) ;
}
2001-04-09 20:54:03 +01:00
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 ;
2008-08-28 17:41:07 +01:00
# endif
# ifdef COROUTINING
CELL * detatt = NULL ;
2001-12-02 16:54:39 +00:00
# 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 ) ) {
2006-03-20 19:51:44 +00:00
/* perform early reset */
/* reset term to be a variable */
2001-04-09 20:54:03 +01:00
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
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 {
2008-08-28 17:41:07 +01:00
if ( hp > ( CELL * ) Yap_GlobalBase & & hp < H0 ) {
if ( ! detatt | | hp > = detatt ) {
mark_att_var ( hp ) ;
} else {
trail_cell = TrailTerm ( trail_base ) = ( CELL ) trail_base ;
discard_trail_entries + + ;
}
} else {
if ( trail_cell = = ( CELL ) trail_base )
discard_trail_entries + + ;
2002-05-03 16:30:36 +01:00
# ifdef FROZEN_STACKS
2008-08-28 17:41:07 +01:00
else {
mark_external_reference ( & TrailVal ( trail_base ) ) ;
}
2002-05-03 16:30:36 +01:00
# endif
2008-08-28 17:41:07 +01:00
}
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 ;
2006-04-28 17:14:05 +01:00
if ( ( ADDR ) nsTR > Yap_TrailTop - 1024 ) {
2007-03-21 18:32:50 +00:00
gc_growtrail ( TRUE , begsTR , old_cont_top0 ) ;
2006-04-28 17:14:05 +01:00
}
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 */
2006-12-30 03:25:47 +00:00
CELL * cptr = RepPair ( trail_cell ) ;
if ( cptr > ( CELL * ) Yap_GlobalBase & & cptr < H0 ) {
trail_base + + ;
continue ;
}
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 .
*/
2006-04-21 22:50:33 +01:00
if ( cptr < ( CELL * ) gc_B & & cptr > = gc_H ) {
goto remove_trash_entry ;
2008-08-28 17:41:07 +01:00
} else if ( ! detatt & & cptr = = RepAppl ( DelayedVars ) + 1 ) {
detatt = cptr ;
} else if ( cptr > ( CELL * ) Yap_GlobalBase & & cptr < H0 ) {
/* MABINDING that should be recovered */
if ( detatt & & cptr > = detatt ) {
goto remove_trash_entry ;
} else {
/* This attributed variable is still in play */
mark_att_var ( cptr ) ;
}
2006-04-21 22:50:33 +01:00
}
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*/
2006-04-21 22:50:33 +01:00
Term t0 = TrailTerm ( trail_base + 1 ) ;
if ( ! IsAtomicTerm ( t0 ) ) {
CELL * next = GET_NEXT ( t0 ) ;
/* check if we have a garbage entry, where we are setting a
pointer to ourselves . */
if ( next < ( CELL * ) gc_B & & next > = gc_H ) {
goto remove_trash_entry ;
}
}
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 ) ) ;
}
2006-12-29 01:57:50 +00:00
# ifdef TABLING
mark_external_reference ( & ( TrailVal ( trail_base ) ) ) ;
# else
2004-04-16 21:38:54 +01:00
trail_base + + ;
mark_external_reference ( & ( TrailTerm ( trail_base ) ) ) ;
2005-11-07 15:35:47 +00:00
# endif
2004-04-16 21:38:54 +01:00
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 {
2006-04-21 22:50:33 +01:00
remove_trash_entry :
2001-04-09 20:54:03 +01:00
/* 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
2005-11-07 15:35:47 +00:00
# ifndef TABLING
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
2005-11-07 15:35:47 +00:00
# endif /* TABLING */
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
}
2006-12-29 01:57:50 +00:00
# if TABLING
/*
Ugly , but needed : we ' re not really sure about what were the new
values until the very end
*/
{
gc_ma_hash_entry * gl = gc_ma_h_list ;
while ( gl ) {
mark_external_reference ( & ( TrailVal ( gl - > loc + 1 ) ) ) ;
gl = gl - > more ;
}
}
# endif
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 - - ;
}
}
2008-08-27 17:12:03 +01:00
# ifdef COROUTINING
static void
mark_delays ( attvar_record * top , attvar_record * bottom )
{
attvar_record * attv = ( attvar_record * ) top ;
for ( ; attv < bottom ; attv + + ) {
2008-08-28 17:41:07 +01:00
/* only mark what is accessible */
if ( IsVarTerm ( attv - > Done ) & & IsUnboundVar ( & attv - > Done ) ) {
2008-08-27 17:12:03 +01:00
mark_external_reference2 ( & attv - > Done ) ;
mark_external_reference2 ( & attv - > Value ) ;
mark_external_reference2 ( & attv - > Atts ) ;
2008-08-28 17:41:07 +01:00
}
2008-08-27 17:12:03 +01:00
}
}
# else
# define mark_delays(T,B)
# endif
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
{
2006-11-27 17:42:03 +00:00
OPCODE trust_lu = Yap_opcode ( _trust_logical ) ;
2008-09-05 05:22:19 +01:00
yamop * lu_cl0 = NEXTOP ( PredLogUpdClause0 - > CodeOfPred , Otapl ) ,
* lu_cl = NEXTOP ( PredLogUpdClause - > CodeOfPred , Otapl ) ,
* lu_cle = NEXTOP ( PredLogUpdClauseErase - > CodeOfPred , Otapl ) ,
* su_cl = NEXTOP ( PredStaticClause - > CodeOfPred , Otapl ) ;
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 */
2005-11-15 00:50:49 +00:00
# ifdef TABLING
if ( depfr ! = NULL & & gc_B > = DepFr_cons_cp ( depfr ) ) {
gc_B = DepFr_cons_cp ( depfr ) ;
depfr = DepFr_next ( depfr ) ;
}
# endif
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 */
mark_trail ( saved_TR , gc_B - > cp_tr , gc_B - > cp_h , gc_B ) ;
saved_TR = gc_B - > cp_tr ;
}
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 ) ,
2008-09-05 05:22:19 +01:00
- gc_B - > cp_cp - > u . Osblp . s / ( ( OPREG ) sizeof ( CELL ) ) ,
gc_B - > cp_cp - > u . Osblp . bmap
2001-04-09 20:54:03 +01:00
) ;
} 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 ,
2008-08-28 04:43:00 +01:00
EnvSize ( ( yamop * ) ( gc_B - > cp_cp ) ) ,
EnvBMap ( ( yamop * ) ( 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 ) ;
2005-12-07 12:55:31 +00:00
if ( IsVarTerm ( ( CELL ) ref ) ) {
mark_ref_in_use ( ref ) ;
} else {
2001-04-09 20:54:03 +01:00
if ( ONCODE ( ( CELL ) ref ) ) {
mark_db_fixed ( RepAppl ( ( CELL ) ref ) ) ;
}
}
B = old_b ;
}
2008-09-05 05:22:19 +01:00
nargs = rtp - > u . OtapFs . s + rtp - > u . OtapFs . extra ;
2001-04-09 20:54:03 +01:00
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 _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 ) ;
2008-09-05 05:22:19 +01:00
nargs = rtp - > u . Otapl . s ;
2005-07-06 20:34:12 +01:00
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-11-15 00:50:49 +00:00
if ( rtp ) {
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 :
2005-12-07 12:55:31 +00:00
mark_ref_in_use ( ( DBRef ) ClauseCodeToDynamicClause ( gc_B - > cp_ap ) ) ;
2004-09-27 21:45:04 +01:00
case _retry2 :
nargs = 2 ;
break ;
case _retry3 :
nargs = 3 ;
break ;
case _retry4 :
nargs = 4 ;
break ;
2006-10-10 15:08:17 +01:00
case _try_logical :
case _retry_logical :
case _count_retry_logical :
case _profiled_retry_logical :
2006-11-27 17:42:03 +00:00
{
/* find out who owns this sequence of try-retry-trust */
/* I don't like this code, it's a bad idea to do a linear scan,
on the other hand it ' s the only way we can be sure we can reclaim
space
*/
2008-09-05 05:22:19 +01:00
yamop * end = rtp - > u . OtaLl . n ;
2006-11-27 17:42:03 +00:00
while ( end - > opc ! = trust_lu )
2008-09-05 05:22:19 +01:00
end = end - > u . OtaLl . n ;
mark_ref_in_use ( ( DBRef ) end - > u . OtILl . block ) ;
2006-11-27 17:42:03 +00:00
}
2006-10-10 15:08:17 +01:00
/* mark timestamp */
2008-09-05 05:22:19 +01:00
nargs = rtp - > u . OtaLl . s + 1 ;
2006-10-10 15:08:17 +01:00
break ;
case _trust_logical :
case _count_trust_logical :
case _profiled_trust_logical :
/* mark timestamp */
2008-09-05 05:22:19 +01:00
mark_ref_in_use ( ( DBRef ) rtp - > u . OtILl . block ) ;
nargs = rtp - > u . OtILl . d - > ClPred - > ArityOfPE + 1 ;
2006-10-10 15:08:17 +01:00
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 :
2008-09-05 05:22:19 +01:00
nargs = rtp - > u . Otapl . s ;
2001-04-09 20:54:03 +01:00
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 :
2008-09-05 05:22:19 +01:00
nargs = rtp - > u . Otapl . s ;
2001-04-09 20:54:03 +01:00
# 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 | |
2008-01-23 17:57:56 +00:00
gc_B - > cp_ap = = lu_cle | |
2004-04-30 20:50:01 +01:00
gc_B - > cp_ap = = su_cl ) {
2008-01-23 17:57:56 +00:00
yamop * pt = ( yamop * ) IntegerOfTerm ( gc_B - > cp_args [ 1 ] ) ;
if ( gc_B - > cp_ap = = su_cl ) {
mark_db_fixed ( ( CELL * ) pt ) ;
} else {
while ( pt - > opc ! = trust_lu )
2008-09-05 05:22:19 +01:00
pt = pt - > u . OtaLl . n ;
mark_ref_in_use ( ( DBRef ) pt - > u . OtILl . block ) ;
2008-01-23 17:57:56 +00:00
}
2004-04-30 20:50:01 +01:00
}
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
CELL current_tag ;
current_tag = TAG ( * current ) ;
if ( RMARKED ( next ) )
RMARK ( current ) ;
else {
UNRMARK ( current ) ;
RMARK ( next ) ;
}
* current = * next ;
* next = ( CELL ) current | current_tag ;
2001-04-09 20:54:03 +01:00
}
2006-03-22 20:07:28 +00:00
static void
CleanDeadClauses ( void )
{
{
StaticClause * * cptr ;
StaticClause * cl ;
cptr = & ( DeadStaticClauses ) ;
cl = DeadStaticClauses ;
while ( cl ) {
if ( ! ref_in_use ( ( DBRef ) cl ) ) {
char * ocl = ( char * ) cl ;
2006-11-06 18:35:05 +00:00
Yap_ClauseSpace - = cl - > ClSize ;
2006-03-22 20:07:28 +00:00
cl = cl - > ClNext ;
* cptr = cl ;
Yap_FreeCodeSpace ( ocl ) ;
} else {
cptr = & ( cl - > ClNext ) ;
cl = cl - > ClNext ;
}
}
}
{
StaticIndex * * cptr ;
StaticIndex * cl ;
cptr = & ( DeadStaticIndices ) ;
cl = DeadStaticIndices ;
while ( cl ) {
if ( ! ref_in_use ( ( DBRef ) cl ) ) {
char * ocl = ( char * ) cl ;
2006-11-06 18:35:05 +00:00
if ( cl - > ClFlags & SwitchTableMask )
Yap_IndexSpace_SW - = cl - > ClSize ;
else
Yap_IndexSpace_Tree - = cl - > ClSize ;
2006-03-22 20:07:28 +00:00
cl = cl - > SiblingIndex ;
* cptr = cl ;
Yap_FreeCodeSpace ( ocl ) ;
} else {
cptr = & ( cl - > SiblingIndex ) ;
cl = cl - > SiblingIndex ;
}
}
}
{
MegaClause * * cptr ;
MegaClause * cl ;
cptr = & ( DeadMegaClauses ) ;
cl = DeadMegaClauses ;
while ( cl ) {
if ( ! ref_in_use ( ( DBRef ) cl ) ) {
char * ocl = ( char * ) cl ;
2006-11-06 18:35:05 +00:00
Yap_ClauseSpace - = cl - > ClSize ;
2006-03-22 20:07:28 +00:00
cl = cl - > ClNext ;
* cptr = cl ;
Yap_FreeCodeSpace ( ocl ) ;
} else {
cptr = & ( cl - > ClNext ) ;
cl = cl - > ClNext ;
}
}
}
}
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 ;
2001-04-09 20:54:03 +01:00
Int OldHeapUsed = HeapUsed ;
# 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
2006-04-21 22:50:33 +01:00
{
choiceptr current = gc_B ;
choiceptr next = gc_B - > cp_b ;
tr_fr_ptr source , dest ;
/* invert cp ptrs */
current - > cp_b = NULL ;
while ( next ) {
choiceptr n = next ;
next = n - > cp_b ;
n - > cp_b = current ;
current = n ;
}
next = current ;
current = NULL ;
/* next, clean trail */
source = dest = ( tr_fr_ptr ) Yap_TrailBase ;
while ( source < old_TR ) {
while ( next & & source = = next - > cp_tr ) {
choiceptr b = next ;
b - > cp_tr = dest ;
next = b - > cp_b ;
b - > cp_b = current ;
current = b ;
}
CELL trail_cell = TrailTerm ( source ) ;
if ( trail_cell ! = ( CELL ) source ) {
dest + + ;
}
source + + ;
}
while ( next ) {
choiceptr b = next ;
b - > cp_tr = dest ;
next = b - > cp_b ;
b - > cp_b = current ;
current = 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 ) ) ;
}
2006-03-20 19:51:44 +00:00
}
2002-05-03 16:30:36 +01:00
# ifdef FROZEN_STACKS
2006-03-20 19:51:44 +00:00
/* it is complex to recover cells with frozen segments */
TrailVal ( dest ) = TrailVal ( trail_ptr ) ;
if ( MARKED_PTR ( & TrailVal ( dest ) ) ) {
if ( HEAP_PTR ( TrailVal ( dest ) ) ) {
into_relocation_chain ( & TrailVal ( dest ) , GET_NEXT ( TrailVal ( dest ) ) ) ;
2002-05-03 16:30:36 +01:00
}
}
2006-03-20 19:51:44 +00:00
# endif
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
2006-12-30 03:25:47 +00:00
if ( pt0 > ( CELL * ) Yap_GlobalBase & & pt0 < H0 ) {
TrailTerm ( dest ) = trail_cell ;
dest + + ;
trail_ptr + + ;
continue ;
}
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 + + ;
2005-12-07 12:55:31 +00:00
if ( ! ref_in_use ( ( DBRef ) pt0 ) ) {
2002-06-12 17:48:35 +01:00
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
2005-12-07 12:55:31 +00:00
if ( ! ref_in_use ( ( DBRef ) pt0 ) ) {
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 ;
2008-01-24 22:21:27 +00:00
# if defined(YAPOR) || defined(THREADS)
/*
gc may be called when executing a dynamic goal ,
check PP to avoid deadlock
*/
2008-01-24 22:47:14 +00:00
PredEntry * ap = indx - > ClPred ;
2008-01-24 22:21:27 +00:00
if ( ap ! = PP )
LOCK ( ap - > PELock ) ;
# endif
2003-10-14 01:53:10 +01:00
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 */
2006-10-10 15:08:17 +01:00
Yap_ErLogUpdIndex ( indx ) ;
2003-10-14 01:53:10 +01:00
}
2008-01-24 22:21:27 +00:00
# if defined(YAPOR) || defined(THREADS)
if ( ap ! = PP )
UNLOCK ( ap - > PELock ) ;
# endif
2003-10-14 01:53:10 +01:00
} else {
LogUpdClause * cl = ClauseFlagsToLogUpdClause ( pt0 ) ;
2008-01-24 22:21:27 +00:00
# if defined(YAPOR) || defined(THREADS)
PredEntry * ap = cl - > ClPred ;
# endif
2003-10-14 01:53:10 +01:00
int erase ;
2004-04-22 04:24:17 +01:00
2008-01-24 22:21:27 +00:00
# if defined(YAPOR) || defined(THREADS)
if ( ap ! = PP )
LOCK ( ap - > PELock ) ;
# endif
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 ) ;
}
2008-01-24 22:21:27 +00:00
# if defined(YAPOR) || defined(THREADS)
if ( ap ! = PP )
UNLOCK ( ap - > PELock ) ;
# endif
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-04-09 20:54:03 +01:00
}
# if MULTI_ASSIGNMENT_VARIABLES
2001-05-21 21:00:05 +01:00
} else {
2005-11-07 15:35:47 +00:00
# ifdef FROZEN_STACKS
CELL trail_cell = TrailTerm ( trail_ptr + 1 ) ;
CELL old = TrailVal ( trail_ptr ) ;
CELL old1 = TrailVal ( trail_ptr + 1 ) ;
Int marked_ptr = MARKED_PTR ( & TrailTerm ( trail_ptr + 1 ) ) ;
Int marked_val_old = MARKED_PTR ( & TrailVal ( trail_ptr ) ) ;
Int marked_val_ptr = MARKED_PTR ( & TrailVal ( trail_ptr + 1 ) ) ;
TrailTerm ( dest + 1 ) = TrailTerm ( dest ) = trail_cell ;
2006-12-29 01:57:50 +00:00
TrailVal ( dest ) = old ;
TrailVal ( dest + 1 ) = old1 ;
2005-11-07 15:35:47 +00:00
if ( marked_ptr ) {
UNMARK ( & TrailTerm ( dest ) ) ;
UNMARK ( & TrailTerm ( dest + 1 ) ) ;
if ( HEAP_PTR ( trail_cell ) ) {
into_relocation_chain ( & TrailTerm ( dest ) , GET_NEXT ( trail_cell ) ) ;
into_relocation_chain ( & TrailTerm ( dest + 1 ) , GET_NEXT ( trail_cell ) ) ;
}
}
if ( marked_val_old ) {
UNMARK ( & TrailVal ( dest ) ) ;
if ( HEAP_PTR ( old ) ) {
into_relocation_chain ( & TrailVal ( dest ) , GET_NEXT ( old ) ) ;
}
}
if ( marked_val_ptr ) {
UNMARK ( & TrailVal ( dest + 1 ) ) ;
if ( HEAP_PTR ( old1 ) ) {
into_relocation_chain ( & TrailVal ( dest + 1 ) , GET_NEXT ( old1 ) ) ;
}
}
trail_ptr + + ;
dest + + ;
# else
2004-03-19 11:35:42 +00:00
CELL trail_cell = TrailTerm ( trail_ptr + 2 ) ;
2005-11-07 15:35:47 +00:00
CELL old = TrailTerm ( trail_ptr + 1 ) ;
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 ) ) ;
2005-11-07 15:35:47 +00:00
CELL * ptr ;
/* be sure we don't overwrite before we read */
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 ;
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 ;
2005-11-07 15:35:47 +00:00
# endif
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
2006-05-18 17:55:19 +01:00
if ( OldHeapUsed ) {
fprintf ( Yap_stderr ,
" %% 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 ) ;
}
2002-06-12 17:48:35 +01:00
}
2006-03-22 20:07:28 +00:00
CleanDeadClauses ( ) ;
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 ) ;
2008-08-28 04:43:00 +01:00
size = EnvSize ( ( yamop * ) ( gc_ENV [ E_CP ] ) ) ; /* size = EnvSize(CP) */
pvbmap = EnvBMap ( ( yamop * ) ( gc_ENV [ E_CP ] ) ) ;
2001-04-09 20:54:03 +01:00
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 ,
2008-08-28 04:43:00 +01:00
EnvSize ( ( yamop * ) ( gc_B - > cp_cp ) ) ,
EnvBMap ( ( yamop * ) ( gc_B - > cp_cp ) ) ) ;
2004-09-27 21:45:04 +01:00
/* 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
2005-11-15 00:50:49 +00:00
# ifdef TABLING
if ( depfr ! = NULL & & gc_B > = DepFr_cons_cp ( depfr ) ) {
gc_B = DepFr_cons_cp ( depfr ) ;
depfr = DepFr_next ( depfr ) ;
}
# endif
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 ) ,
2008-09-05 05:22:19 +01:00
- gc_B - > cp_cp - > u . Osblp . s / ( ( OPREG ) sizeof ( CELL ) ) ,
gc_B - > cp_cp - > u . Osblp . bmap
2001-04-09 20:54:03 +01:00
) ;
break ;
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 ;
2008-09-24 20:45:12 +01:00
sweep_environments ( gc_B - > cp_env , EnvSize ( gc_B - > cp_cp ) , EnvBMap ( gc_B - > cp_cp ) ) ;
2005-08-01 16:40:39 +01:00
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 ;
2008-09-24 20:45:12 +01:00
sweep_environments ( gc_B - > cp_env , EnvSize ( gc_B - > cp_cp ) , EnvBMap ( gc_B - > cp_cp ) ) ;
2005-07-06 20:34:12 +01:00
vars_ptr = ( CELL * ) ( GEN_CP ( gc_B ) + 1 ) ;
2008-09-05 05:22:19 +01:00
nargs = rtp - > u . Otapl . s ;
2005-07-06 20:34:12 +01:00
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 :
2005-11-15 00:50:49 +00:00
if ( rtp ) {
2005-07-06 20:34:12 +01:00
int nargs ;
CELL * vars_ptr , vars ;
2008-09-24 20:45:12 +01:00
sweep_environments ( gc_B - > cp_env , EnvSize ( gc_B - > cp_cp ) , EnvBMap ( gc_B - > cp_cp ) ) ;
2005-07-06 20:34:12 +01:00
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 ;
2008-09-24 20:45:12 +01:00
sweep_environments ( gc_B - > cp_env , EnvSize ( gc_B - > cp_cp ) , EnvBMap ( gc_B - > cp_cp ) ) ;
2005-07-06 20:34:12 +01:00
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 ;
2008-09-24 20:45:12 +01:00
sweep_environments ( gc_B - > cp_env , EnvSize ( gc_B - > cp_cp ) , EnvBMap ( gc_B - > cp_cp ) ) ;
2005-07-06 20:34:12 +01:00
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 */
2006-10-10 15:08:17 +01:00
case _try_logical :
case _retry_logical :
case _count_retry_logical :
case _profiled_retry_logical :
/* sweep timestamp */
2008-09-05 05:22:19 +01:00
sweep_b ( gc_B , rtp - > u . OtaLl . s + 1 ) ;
2006-10-10 15:08:17 +01:00
break ;
case _trust_logical :
case _count_trust_logical :
case _profiled_trust_logical :
2008-09-05 05:22:19 +01:00
sweep_b ( gc_B , rtp - > u . OtILl . d - > ClPred - > ArityOfPE + 1 ) ;
2006-10-10 15:08:17 +01:00
break ;
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 */
2008-09-05 05:22:19 +01:00
for ( saved_reg = & ( gc_B - > cp_a1 ) + rtp - > u . OtapFs . s ;
saved_reg < & ( gc_B - > cp_a1 ) + rtp - > u . OtapFs . s + rtp - > u . OtapFs . extra ;
2001-04-09 20:54:03 +01:00
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 :
2008-09-05 05:22:19 +01:00
sweep_b ( gc_B , rtp - > u . Otapl . 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
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 ;
2001-04-09 20:54:03 +01:00
}
static inline choiceptr
2005-11-07 15:35:47 +00:00
update_B_H ( choiceptr gc_B , CELL * current , CELL * dest , CELL * odest
# ifdef TABLING
, dep_fr_ptr * depfrp
# endif
) {
2001-04-09 20:54:03 +01:00
/* also make the value of H in a choicepoint
coherent with the new global
*/
2005-11-07 15:35:47 +00:00
# ifdef TABLING
dep_fr_ptr depfr = * depfrp ;
# endif
2001-04-09 20:54:03 +01:00
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
2005-11-07 15:35:47 +00:00
/* make sure we include consumers */
if ( depfr & & gc_B > = DepFr_cons_cp ( depfr ) ) {
gc_B = DepFr_cons_cp ( depfr ) ;
2005-11-16 01:55:03 +00:00
* depfrp = depfr = DepFr_next ( depfr ) ;
2002-05-03 16:30:36 +01:00
}
2005-07-06 20:34:12 +01:00
# endif /* TABLING */
2001-04-09 20:54:03 +01:00
}
2005-11-07 15:35:47 +00: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 ;
2005-11-07 15:35:47 +00:00
# ifdef TABLING
dep_fr_ptr depfr = LOCAL_top_dep_fr ;
# endif /* TABLING */
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-11-15 00:50:49 +00:00
# ifdef TABLING
if ( depfr ! = NULL & & gc_B > = DepFr_cons_cp ( depfr ) ) {
gc_B = DepFr_cons_cp ( depfr ) ;
depfr = DepFr_next ( depfr ) ;
}
# endif
2005-09-09 18:23:43 +01:00
next_hb = set_next_hb ( gc_B ) ;
2007-09-27 16:25:34 +01:00
dest = H0 + total_marked - 1 ;
2005-09-21 04:49:33 +01:00
2007-09-27 16:25:34 +01:00
gc_B = update_B_H ( gc_B , H , dest + 1 , dest + 2
# ifdef TABLING
, & depfr
# endif
) ;
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 ) ;
2006-08-22 17:12:46 +01:00
if ( in_garbage > 0 ) {
current [ 1 ] = in_garbage ;
in_garbage = 0 ;
}
if ( current < = next_hb ) {
gc_B = update_B_H ( gc_B , current , dest , dest + 1
2005-11-07 15:35:47 +00:00
# ifdef TABLING
2006-08-22 17:12:46 +01:00
, & depfr
2005-11-07 15:35:47 +00:00
# endif
2006-08-22 17:12:46 +01:00
) ;
next_hb = set_next_hb ( gc_B ) ;
}
if ( ccell = = EndSpecials ) {
/* oops, we found a blob */
CELL * ptr = current - 1 ;
UInt nofcells ;
while ( ! MARKED_PTR ( ptr ) ) ptr - - ;
nofcells = current - ptr ;
ptr + + ;
MARK ( ptr ) ;
2006-08-30 02:06:30 +01:00
# ifdef DEBUG
2006-08-22 17:12:46 +01:00
found_marked + = nofcells ;
2006-08-30 02:06:30 +01:00
# endif
2006-08-22 17:12:46 +01:00
/* first swap the tag so that it will be seen by the next step */
current [ 0 ] = ptr [ 0 ] ;
ptr [ 0 ] = EndSpecials ;
dest - = nofcells ;
current = ptr ;
continue ;
/* process the functor on a separate cycle */
2001-04-09 20:54:03 +01:00
}
# 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
UNRMARK ( current ) ;
* current = ( CELL ) dest ; /* no tag */
}
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
2006-08-22 17:12:46 +01:00
if ( dest ! = start_from - 1 )
fprintf ( Yap_stderr , " %% Bad Dest (%d): %p should be %p \n " ,
GcCalls ,
dest ,
start_from ) ;
2001-04-09 20:54:03 +01:00
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 ) ;
2006-08-22 17:12:46 +01:00
if ( uccur = = EndSpecials ) {
CELL * old_dest = dest ;
2006-05-19 14:48:11 +01:00
2006-08-22 17:12:46 +01:00
dest + + ;
current + + ;
while ( ! MARKED_PTR ( current ) ) {
2001-04-09 20:54:03 +01:00
* dest + + = * current + + ;
}
2006-08-22 17:12:46 +01:00
* old_dest = * current ;
* dest + + = EndSpecials ;
2001-04-09 20:54:03 +01:00
# ifdef DEBUG
2006-08-22 17:12:46 +01:00
found_marked + = ( dest - old_dest ) ;
2001-04-09 20:54:03 +01:00
# endif
continue ;
}
# ifdef DEBUG
found_marked + + ;
# endif
update_relocation_chain ( current , dest ) ;
ccur = * current ;
next = GET_NEXT ( ccur ) ;
2005-12-03 03:03:18 +00:00
if ( HEAP_PTR ( ccur ) & &
( next = GET_NEXT ( ccur ) ) < 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
/*
* 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 ;
2006-08-22 17:12:46 +01:00
CELL_PTR dest ;
CELL * next_hb ;
2001-05-02 15:19:10 +01:00
# ifdef DEBUG
Int found_marked = 0 ;
# endif /* DEBUG */
2006-08-22 17:12:46 +01:00
# ifdef TABLING
dep_fr_ptr depfr = LOCAL_top_dep_fr ;
# endif /* TABLING */
choiceptr gc_B = B ;
2001-05-02 15:19:10 +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
*/
2006-08-22 17:12:46 +01:00
# ifdef TABLING
if ( depfr ! = NULL & & gc_B > = DepFr_cons_cp ( depfr ) ) {
gc_B = DepFr_cons_cp ( depfr ) ;
depfr = DepFr_next ( depfr ) ;
}
# endif
next_hb = set_next_hb ( gc_B ) ;
dest = ( CELL_PTR ) H0 + total_marked - 1 ;
2007-09-27 16:25:34 +01:00
gc_B = update_B_H ( gc_B , H , dest + 1 , dest + 2
# ifdef TABLING
, & depfr
# endif
) ;
2001-05-02 15:19:10 +01:00
for ( iptr = iptop - 1 ; iptr > = ibase ; iptr - - ) {
CELL ccell ;
CELL_PTR current ;
current = * iptr ;
ccell = UNMARK_CELL ( * current ) ;
2006-08-22 17:12:46 +01:00
if ( current < = next_hb ) {
gc_B = update_B_H ( gc_B , current , dest , dest + 1
# ifdef TABLING
, & depfr
# endif
) ;
next_hb = set_next_hb ( gc_B ) ;
}
if ( ccell = = EndSpecials ) {
2001-05-02 15:19:10 +01:00
/* oops, we found a blob */
2006-08-22 17:12:46 +01:00
CELL_PTR ptr ;
UInt nofcells ;
2001-05-02 15:19:10 +01:00
2006-08-22 17:12:46 +01:00
/* use the first cell after the functor for all our dirty tricks */
ptr = iptr [ - 1 ] + 1 ;
nofcells = current - ptr ;
2001-05-02 15:19:10 +01:00
# ifdef DEBUG
2006-08-22 17:12:46 +01:00
found_marked + = ( nofcells + 1 ) ;
2001-05-02 15:19:10 +01:00
# endif /* DEBUG */
2006-08-22 17:12:46 +01:00
dest - = nofcells + 1 ;
2001-05-02 15:19:10 +01:00
/* this one's being used */
2006-08-22 17:12:46 +01:00
/* make the second step see the EndSpecial tag */
current [ 0 ] = ptr [ 0 ] ;
ptr [ 0 ] = EndSpecials ;
iptr [ 0 ] = ptr ;
continue ;
2001-05-02 15:19:10 +01:00
}
# ifdef DEBUG
found_marked + + ;
# endif /* DEBUG */
2006-08-22 17:12:46 +01:00
update_relocation_chain ( current , dest ) ;
2001-05-02 15:19:10 +01:00
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 */
2006-08-22 17:12:46 +01:00
UNRMARK ( current ) ;
* current = ( CELL ) dest ; /* no tag */
2004-09-30 20:51:54 +01:00
}
2001-05-02 15:19:10 +01:00
}
2006-08-22 17:12:46 +01:00
dest - - ;
2001-05-02 15:19:10 +01:00
}
# ifdef DEBUG
2006-08-22 17:12:46 +01:00
if ( dest ! = H0 - 1 )
fprintf ( Yap_stderr , " %% Bad Dest (%d): %p should be %p \n " ,
GcCalls ,
dest ,
H0 - 1 ) ;
2001-05-02 15:19:10 +01:00
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
*/
2006-08-22 17:12:46 +01:00
dest = H0 ;
2001-05-02 15:19:10 +01:00
for ( iptr = ibase ; iptr < iptop ; iptr + + ) {
CELL_PTR next ;
CELL * current = * iptr ;
CELL ccur = * current ;
CELL uccur = UNMARK_CELL ( ccur ) ;
2006-08-22 17:12:46 +01:00
if ( uccur = = EndSpecials ) {
CELL * old_dest = dest ;
/* leave a hole */
dest + + ;
current + + ;
while ( ! MARKED_PTR ( current ) ) {
2001-05-02 15:19:10 +01:00
* dest + + = * current + + ;
}
2006-08-22 17:12:46 +01:00
/* fill in hole */
* old_dest = * current ;
* dest + + = EndSpecials ;
2001-05-02 15:19:10 +01:00
# ifdef DEBUG
2006-08-22 17:12:46 +01:00
found_marked + = dest - old_dest ;
2001-05-02 15:19:10 +01:00
# 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 ) ;
2006-08-22 17:12:46 +01:00
dest + + ;
2001-05-02 15:19:10 +01:00
} else {
/* just move current cell */
2006-08-22 17:12:46 +01:00
* dest + + = ccur = UNMARK_CELL ( ccur ) ;
2001-05-02 15:19:10 +01:00
}
}
# ifdef DEBUG
2006-08-22 17:12:46 +01:00
if ( H0 + total_marked ! = dest )
fprintf ( Yap_stderr , " %% Downward (%d): %p total against %p found \n " ,
GcCalls ,
H0 + total_marked ,
dest ) ;
2001-05-02 15:19:10 +01:00
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
2006-08-22 17:12:46 +01:00
H = dest ; /* reset H */
2001-05-02 15:19:10 +01:00
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
2005-12-07 17:53:30 +00:00
set_conditionals ( tr_fr_ptr str ) {
while ( str ! = sTR0 ) {
2001-12-02 16:54:39 +00:00
CELL * cptr ;
2005-12-07 17:53:30 +00:00
str - = 2 ;
cptr = ( CELL * ) TrailTerm ( str + 1 ) ;
* cptr = TrailTerm ( str ) ;
2001-04-26 15:44:43 +01:00
}
2007-03-21 23:49:41 +00:00
sTR = sTR0 = NULL ;
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 ;
2006-04-21 22:50:33 +01:00
prev_HB = H ;
2001-04-09 20:54:03 +01:00
# 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 ;
2006-03-30 02:11:10 +01:00
/* make sure we set HB before we do any variable shunting!!! */
2002-02-28 18:25:55 +00:00
# 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 ;
2006-04-21 22:50:33 +01:00
/* These two must be marked first so that our trail optimisation won't lose
values */
mark_regs ( old_TR ) ; /* active registers & trail */
2001-04-09 20:54:03 +01:00
/* active environments */
2008-08-27 17:12:03 +01:00
mark_delays ( ( attvar_record * ) max , ( attvar_record * ) H0 ) ;
2008-08-28 04:43:00 +01:00
mark_environments ( current_env , EnvSize ( curp ) , EnvBMap ( 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 ;
2006-08-05 04:06:31 +01:00
char * bpb = Yap_bp + ( base - ( CELL * ) Yap_GlobalBase ) ;
2005-09-21 04:49:33 +01:00
while ( ptr < max ) {
2006-09-01 21:14:42 +01:00
if ( * bpb ) {
2005-09-21 04:49:33 +01:00
if ( HEAP_PTR ( * ptr ) ) {
into_relocation_chain ( ptr , GET_NEXT ( * ptr ) ) ;
}
}
ptr + + ;
2006-08-05 04:06:31 +01:00
bpb + + ;
2005-09-21 04:49:33 +01:00
}
}
2001-04-09 20:54:03 +01:00
# ifdef COROUTINING
static void
2006-08-22 17:12:46 +01:00
sweep_delays ( CELL * max , CELL * myH0 )
2001-04-09 20:54:03 +01:00
{
2006-08-22 17:12:46 +01:00
while ( max < myH0 ) {
if ( MARKED_PTR ( max ) ) {
UNMARK ( max ) ;
if ( HEAP_PTR ( * max ) ) {
into_relocation_chain ( max , GET_NEXT ( * max ) ) ;
2001-04-09 20:54:03 +01:00
}
}
2006-08-22 17:12:46 +01:00
max + + ;
2001-04-09 20:54:03 +01:00
}
}
# 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 )
{
2006-08-22 17:12:46 +01:00
CELL * CurrentH0 = NULL , * myH0 = H0 ;
2005-09-21 04:49:33 +01:00
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
2006-08-22 17:12:46 +01:00
sweep_delays ( max , myH0 ) ;
2001-04-09 20:54:03 +01:00
# endif
2008-08-28 04:43:00 +01:00
sweep_environments ( current_env , EnvSize ( curp ) , EnvBMap ( curp ) ) ;
2001-05-02 15:19:10 +01:00
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
2006-08-22 17:12:46 +01:00
/*
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 ) ;
2006-08-22 17:12:46 +01:00
*/
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-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
}
2005-12-07 12:55:31 +00:00
static int
2001-04-09 20:54:03 +01:00
do_gc ( Int predarity , CELL * current_env , yamop * nextop )
{
2004-10-27 16:56:34 +01:00
Int heap_cells ;
int gc_verbose ;
2005-12-07 12:55:31 +00:00
volatile 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 ;
2006-03-06 14:04:57 +00:00
UInt gc_phase ;
2007-03-21 18:32:50 +00:00
UInt alloc_sz ;
2001-04-09 20:54:03 +01:00
2004-10-27 16:56:34 +01:00
heap_cells = H - H0 ;
gc_verbose = is_gc_verbose ( ) ;
effectiveness = 0 ;
gc_trace = FALSE ;
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 ;
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 ) {
2008-01-23 17:57:56 +00:00
# if defined(YAPOR) || defined(THREADS)
fprintf ( Yap_stderr , " %% Worker Id %d: \n " , worker_id ) ;
# endif
2004-10-06 17:55:48 +01:00
fprintf ( Yap_stderr , " %% Start of garbage collection %d: \n " , GcCalls ) ;
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-12-17 03:25:39 +00:00
return - 1 ;
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 ( ) ;
2004-12-07 13:46:53 +00:00
# if COROUTINING
2007-03-21 18:32:50 +00:00
max = ( CELL * ) DelayTop ( ) ;
while ( max - ( CELL * ) Yap_GlobalBase < 1024 + ( 2 * NUM_OF_ATTS ) ) {
if ( ! Yap_growglobal ( & current_env ) ) {
Yap_Error ( OUT_OF_STACK_ERROR , TermNil , Yap_ErrorMessage ) ;
return - 1 ;
2004-09-16 18:29:08 +01:00
}
2007-03-21 18:32:50 +00:00
max = ( CELL * ) DelayTop ( ) ;
2004-09-16 18:29:08 +01:00
}
2007-03-21 18:32:50 +00:00
# else
max = NULL ;
# endif
2005-12-07 12:55:31 +00:00
if ( setjmp ( Yap_gc_restore ) = = 2 ) {
2007-03-21 18:32:50 +00:00
UInt sz ;
2005-12-07 12:55:31 +00:00
/* we cannot recover, fail system */
2006-01-02 02:16:19 +00:00
restore_machine_regs ( ) ;
2007-03-21 18:32:50 +00:00
sz = Yap_TrailTop - ( ADDR ) OldTR ;
/* ask for double the size */
sz = 2 * sz ;
2005-12-07 12:55:31 +00:00
TR = OldTR ;
2007-03-21 18:32:50 +00:00
* - - ASP = ( CELL ) current_env ;
2005-12-07 12:55:31 +00:00
if (
2007-03-21 18:32:50 +00:00
! Yap_growtrail ( sz , FALSE )
2005-12-07 12:55:31 +00:00
) {
2007-03-21 23:23:46 +00:00
Yap_Error ( OUT_OF_TRAIL_ERROR , TermNil , " out of %lB during gc " , sz ) ;
2005-12-07 12:55:31 +00:00
return - 1 ;
} else {
2006-04-21 22:50:33 +01:00
total_marked = 0 ;
total_oldies = 0 ;
# ifdef COROUTING
total_smarked = 0 ;
# endif
discard_trail_entries = 0 ;
2005-12-07 12:55:31 +00:00
current_env = ( CELL * ) * ASP ;
ASP + + ;
# if COROUTINING
2007-03-21 18:32:50 +00:00
max = ( CELL * ) DelayTop ( ) ;
2005-12-07 12:55:31 +00:00
# endif
}
}
2007-03-21 23:49:41 +00:00
# if EASY_SHUNTING
sTR0 = sTR = NULL ;
# endif
2007-03-21 18:32:50 +00:00
total_marked = 0 ;
total_oldies = 0 ;
# ifdef COROUTING
total_smarked = 0 ;
# endif
discard_trail_entries = 0 ;
alloc_sz = ( CELL * ) Yap_TrailTop - ( CELL * ) Yap_GlobalBase ;
Yap_bp = Yap_PreAllocCodeSpace ( ) ;
while ( Yap_bp + alloc_sz > ( char * ) AuxSp ) {
/* not enough space */
* - - ASP = ( CELL ) current_env ;
Yap_bp = ( char * ) Yap_ExpandPreAllocCodeSpace ( alloc_sz , NULL ) ;
if ( ! Yap_bp )
return - 1 ;
current_env = ( CELL * ) * ASP ;
ASP + + ;
# if COROUTINING
max = ( CELL * ) DelayTop ( ) ;
# endif
}
memset ( ( void * ) Yap_bp , 0 , alloc_sz ) ;
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 */
2007-10-05 19:24:30 +01:00
HGEN = VarOfTerm ( Yap_ReadTimedVar ( GcGeneration ) ) ;
2007-03-21 18:32:50 +00:00
2006-03-06 14:04:57 +00:00
gc_phase = ( UInt ) IntegerOfTerm ( Yap_ReadTimedVar ( GcPhase ) ) ;
2005-10-18 18:04:43 +01:00
/* old HGEN are not very reliable, but still may have data to recover */
2006-03-06 14:04:57 +00:00
if ( gc_phase ! = GcCurrentPhase ) {
HGEN = H0 ;
2005-10-18 18:04:43 +01:00
}
2005-09-21 04:49:33 +01:00
/* fprintf(stderr,"HGEN is %ld, %p, %p/%p\n", IntegerOfTerm(Yap_ReadTimedVar(GcGeneration)), HGEN, H,H0);*/
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 ) ;
2007-03-21 18:32:50 +00:00
/* make sure we clean bits after a reset */
2001-04-09 20:54:03 +01:00
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 {
2006-03-06 14:04:57 +00:00
if ( HGEN ! = H0 ) {
HGEN = H0 ;
GcCurrentPhase + + ;
}
2005-09-21 04:49:33 +01:00
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 ) {
2005-11-07 15:35:47 +00:00
fprintf ( Yap_stderr , " %% Mark: Marked %ld cells of %ld (efficiency: %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 ;
2005-09-21 04:49:33 +01:00
/* fprintf(Yap_stderr,"NEW HGEN %ld (%ld)\n", H-H0, HGEN-H0);*/
2007-10-05 19:24:30 +01:00
{
Term t = MkVarTerm ( ) ;
Yap_UpdateTimedVar ( GcGeneration , t ) ;
}
2006-03-06 14:04:57 +00:00
Yap_UpdateTimedVar ( GcPhase , MkIntegerTerm ( GcCurrentPhase ) ) ;
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 )
{
2007-04-10 23:13:21 +01:00
if ( Yap_PrologMode = = BootMode )
return FALSE ;
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 )
{
2007-04-10 23:13:21 +01:00
if ( Yap_PrologMode = = BootMode )
return FALSE ;
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
}
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 ;
2008-01-23 17:57:56 +00:00
int gc_on = FALSE , gc_t = FALSE ;
2001-04-09 20:54:03 +01:00
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 ) ;
2008-01-23 17:57:56 +00:00
gc_t = TRUE ;
2003-02-11 16:33:24 +00:00
} else {
2008-01-23 17:57:56 +00:00
/* only go exponential for the first 6 calls, that would ask about 2MB minimum */
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 + + ;
2007-10-05 19:24:30 +01:00
HGEN = VarOfTerm ( Yap_ReadTimedVar ( GcGeneration ) ) ;
2005-11-16 02:13:26 +00:00
if ( gc_on & & ! ( Yap_PrologMode & InErrorMode ) & &
/* make sure there is a point in collecting the heap */
2008-09-24 00:11:22 +01:00
( ASP - H0 ) * sizeof ( CELL ) > gc_lim & &
2007-03-21 18:32:50 +00:00
H - HGEN > ( LCL0 - ASP ) / 2 ) {
2001-04-09 20:54:03 +01:00
effectiveness = do_gc ( predarity , current_env , nextop ) ;
2005-12-07 12:55:31 +00:00
if ( effectiveness < 0 )
return FALSE ;
2008-01-23 17:57:56 +00:00
if ( effectiveness > 90 & & ! gc_t ) {
while ( gc_margin < ( H - H0 ) / sizeof ( CELL ) )
2003-05-19 14:04:09 +01:00
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 ) {
2007-10-18 09:24:16 +01:00
LeaveGCMode ( ) ;
2008-01-24 00:11:59 +00: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
}
2007-10-18 09:24:16 +01:00
static void
LeaveGCMode ( )
{
if ( Yap_PrologMode & GCMode )
Yap_PrologMode & = ~ GCMode ;
if ( Yap_PrologMode & AbortMode ) {
Yap_PrologMode & = ~ AbortMode ;
Yap_Error ( PURE_ABORT , TermNil , " " ) ;
/* in case someone mangles the P register */
save_machine_regs ( ) ;
# if _MSC_VER || defined(__MINGW32__)
/* don't even think about trying this */
# else
# if PUSH_REGS
restore_absmi_regs ( & Yap_standard_regs ) ;
# endif
siglongjmp ( Yap_RestartEnv , 1 ) ;
# endif
}
}
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 ) ;
2007-10-18 09:24:16 +01:00
LeaveGCMode ( ) ;
2006-01-02 02:16:19 +00:00
if ( Yap_PrologMode & GCMode )
Yap_PrologMode & = ~ GCMode ;
2004-06-29 20:04:46 +01:00
return res ;
2003-05-19 14:04:09 +01:00
}
int
Yap_gcl ( UInt gc_lim , Int predarity , CELL * current_env , yamop * nextop )
{
2007-10-18 09:24:16 +01:00
int res ;
Yap_PrologMode | = GCMode ;
res = call_gc ( gc_lim + CalculateStackGap ( ) * sizeof ( CELL ) , predarity , current_env , nextop ) ;
LeaveGCMode ( ) ;
return res ;
2003-05-19 14:04:09 +01:00
}
2001-04-09 20:54:03 +01:00
static Int
p_gc ( void )
{
2007-10-18 09:24:16 +01:00
int res ;
Yap_PrologMode | = GCMode ;
2008-08-28 04:43:00 +01:00
if ( P - > opc = = Yap_opcode ( _execute_cpred ) )
res = do_gc ( 0 , ENV , CP ) > = 0 ;
else
res = do_gc ( 0 , ENV , P ) > = 0 ;
2007-10-18 09:24:16 +01:00
LeaveGCMode ( ) ;
return res ;
2001-04-09 20:54:03 +01:00
}
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
}