void *list_next(list_t *l) { int v; if(l->q>=l->m) { if( (l->mode & LIST_FIXEDMODE)!=0) { assert(0); return NULL; } if( (l->mode & LIST_EXPMODE)!=0) { if(l->s<(1024*1024)) { if((l->m*l->s)>(1024*1024*16)) list_hint(l,l->m+((1024*1024*16)/l->s)); else list_hint(l,2*( (l->m==0)?16:l->m) ); } else list_hint(l,l->m+1); } else { v=l->m+(l->mode&LIST_MODECHUNK); if(v<l->m)v=l->m+1; list_hint(l, v); } } return ((char *)(l->d))+(l->s * l->q++); }
static void note_new_vars( int line, const char *file ) { list new_arenas; list new_free; int err; const where *w; if ( !file ) { return; } #ifdef SANITY free_list_sane( ); #endif w = get_where( line, file ); /*fprintf(stderr, "note_new_vars(%d, \"%s\")\n", line, file); */ if ( err = list_build( &new_arenas, PL_sv_arenaroot, list_hint( ¤t_arenas ) ), ERR_None != err ) { nomem( ); } if ( err = list_build( &new_free, PL_sv_root, list_hint( ¤t_free ) ), ERR_None != err ) { nomem( ); } if ( note_init_done ) { /* Scan the lists looking for new arenas and deleted * free slots. A deleted free slot implies the creation of a new * variable. */ list_true_diff( ¤t_arenas, &new_arenas, w, new_arena, free_arena ); list_true_diff( &new_free, ¤t_free, w, new_var, free_var ); list_delete( ¤t_arenas ); list_delete( ¤t_free ); } /* Roll round to new versions of lists */ current_arenas = new_arenas; current_free = new_free; note_init_done = 1; }
/* Sanity check - compare the free list with the list of free SVs in the arenas */ static void free_list_sane( void ) { list real_free; list comp_free; int err; SV *sva; long diff; /* Get the real free list */ if ( err = list_build( &real_free, PL_sv_root, list_hint( ¤t_free ) ), ERR_None != err ) { nomem( ); } /* Get the list of all the free SVs in all the arenas */ if ( err = list_init( &comp_free, list_hint( &real_free ) ), ERR_None != err ) { nomem( ); } for ( sva = PL_sv_arenaroot; sva; sva = ( SV * ) SvANY( sva ) ) { SV *sv = sva + 1; SV *svend = &sva[SvREFCNT( sva )]; while ( sv < svend ) { if ( free_sv( sv ) ) { if ( err = list_append( &comp_free, sv ), ERR_None != err ) { nomem( ); } } ++sv; } } diff = list_true_diff( &real_free, &comp_free, NULL, in_free_only, in_comp_only ); if ( diff != 0 ) { fprintf( stderr, "Lists have %ld differences, stopping\n", diff ); fprintf( stderr, "%ld items in free list, %ld free items in arenas\n", ( long ) list_used( &real_free ), ( long ) list_used( &comp_free ) ); exit( 1 ); } }
void list_dup(list_t *newl, list_t *oldl) { void *d; list_copyfrom(newl,oldl); list_hint(newl,oldl->q); d=list_block_next(newl,oldl->q); memcpy(d,oldl->d,oldl->s*oldl->q); }
void list_append(list_t *growing, list_t *copyfrom) { void *d; if(copyfrom==NULL)return; assert(growing->s==copyfrom->s); if(copyfrom->q==0)return; list_hint(growing,growing->q+copyfrom->q); d=list_block_next(growing,copyfrom->q); memcpy(d,copyfrom->d,copyfrom->s*copyfrom->q); }
void *list_block_next(list_t *l, int qty) { void *r; if((l->q+qty)>=l->m) list_hint(l, l->q+qty); r=((char*)l->d)+(l->s*l->q); l->q+=qty; return r; }
void list_shrink(list_t *l) { list_hint(l,l->q); }