pike.git / src / array.c

version» Context lines:

pike.git/src/array.c:16:   #include "pike_types.h"   #include "fsort.h"   #include "builtin_functions.h"   #include "pike_memory.h"   #include "gc.h"   #include "main.h"   #include "security.h"   #include "stuff.h"   #include "bignum.h"    - RCSID("$Id: array.c,v 1.72 2000/05/24 02:20:43 hubbe Exp $"); + RCSID("$Id: array.c,v 1.73 2000/06/09 22:43:04 mast Exp $");      struct array empty_array=   {    1, /* Never free */   #ifdef PIKE_SECURITY    0,   #endif    &empty_array, /* Next */    &empty_array, /* previous (circular) */    0, /* Size = 0 */    0, /* malloced Size = 0 */    0, /* no types */    0, /* no flags */   };    -  + struct array *gc_internal_array = &empty_array; + static struct array *gc_mark_array_pos = 0;         /* Allocate an array, this might be changed in the future to    * allocate linked lists or something    * NOTE: the new array have zero references    */      struct array *low_allocate_array(INT32 size,INT32 extra_space)   {    struct array *v;
pike.git/src/array.c:65:    GC_ALLOC(v);          /* for now, we don't know what will go in here */    v->type_field=BIT_MIXED | BIT_UNFINISHED;    v->flags=0;       v->malloced_size=size+extra_space;    v->size=size;    v->refs=1; -  v->prev=&empty_array; -  v->next=empty_array.next; -  empty_array.next=v; -  v->next->prev=v; +  LINK_ARRAY(v);       INITIALIZE_PROT(v);       for(e=0;e<v->size;e++)    {    ITEM(v)[e].type=T_INT;    ITEM(v)[e].subtype=NUMBER_NUMBER;    ITEM(v)[e].u.integer=0;    }       return v;   }      /*    * Free an array without freeing the values inside it    */   static void array_free_no_free(struct array *v)   { -  struct array *next,*prev; +  if (gc_internal_array != &empty_array) { +  if (v == gc_internal_array) +  gc_internal_array = v->next; +  if (v == gc_mark_array_pos) +  gc_mark_array_pos = v->next; +  } +  UNLINK_ARRAY(v);    -  next = v->next; -  prev = v->prev; -  -  v->prev->next=next; -  v->next->prev=prev; -  +     free((char *)v);    -  GC_FREE(v); +  GC_FREE();   }      /*    * Free an array, call this when the array has zero references    */   void really_free_array(struct array *v)   {   #ifdef PIKE_DEBUG    if(v == & empty_array)    fatal("Tried to free the empty_array.\n");
pike.git/src/array.c:1774: Inside #if defined(PIKE_DEBUG)
   check_array(a);       a=a->next;    if(!a)    fatal("Null pointer in array list.\n");    } while (a != & empty_array);   }   #endif /* PIKE_DEBUG */       - void gc_mark_array_as_referenced(struct array *a) + static void gc_check_array(struct array *a)   { -  int e; -  if(gc_mark(a) && a->type_field & BIT_COMPLEX) +  if(a->type_field & BIT_COMPLEX)    { -  +  TYPE_FIELD t;    if (a->flags & ARRAY_WEAK_FLAG) -  for (e=0; e<a->size; e++) -  { -  if (a->item[e].type == T_OBJECT && a->item[e].u.object->prog && -  a->item[e].u.object->prog->flags & PROGRAM_NO_WEAK_FREE) -  gc_mark_svalues(a->item + e, 1); -  } +  t=debug_gc_check_weak_svalues(ITEM(a), a->size, T_ARRAY, a);    else -  gc_mark_svalues(ITEM(a), a->size); +  t=debug_gc_check_svalues(ITEM(a), a->size, T_ARRAY, a); +  +  /* Ugly, but we are not allowed to change type_field +  * at the same time as the array is being built... +  * Actually we just need better primitives for building arrays. +  */ +  if(!(a->type_field & BIT_UNFINISHED) || a->refs!=1) +  a->type_field = t; +  else +  a->type_field |= t;    }   }    - static void gc_check_array(struct array *a) + static void gc_recurse_weak_array(struct array *a, +  TYPE_FIELD (*recurse_fn)(struct svalue *, int))   { -  if(a->type_field & BIT_COMPLEX) -  { +  int e;    TYPE_FIELD t; -  t=debug_gc_check_svalues(ITEM(a), a->size, T_ARRAY, a); +     -  + #ifdef PIKE_DEBUG +  if(!(a->flags & ARRAY_WEAK_FLAG)) +  fatal("Array is not weak.\n"); + #endif +  +  if(a->flags & ARRAY_WEAK_SHRINK) { +  int d=0; +  t = 0; +  for(e=0;e<a->size;e++) +  if (!recurse_fn(a->item+e, 1)) { +  a->item[d++]=a->item[e]; +  t |= 1 << a->item[e].type; +  } +  a->size=d; +  } +  else +  if (!(t = recurse_fn(a->item, a->size))) +  t = a->type_field; +     /* Ugly, but we are not allowed to change type_field    * at the same time as the array is being built...    * Actually we just need better primitives for building arrays.    */    if(!(a->type_field & BIT_UNFINISHED) || a->refs!=1)    a->type_field = t;    else    a->type_field |= t;   } -  +  + void gc_mark_array_as_referenced(struct array *a) + { +  int e; +  if(gc_mark(a)) { + #ifdef PIKE_DEBUG +  if (a == &empty_array) fatal("Trying to gc mark empty_array.\n"); + #endif +  +  if (a == gc_mark_array_pos) +  gc_mark_array_pos = a->next; +  if (a == gc_internal_array) +  gc_internal_array = a->next; +  else { +  UNLINK_ARRAY(a); +  LINK_ARRAY(a); /* Linked in first. */    }    -  +  if (a->type_field & BIT_COMPLEX) +  { +  if (a->flags & ARRAY_WEAK_FLAG) +  gc_recurse_weak_array(a, gc_mark_weak_svalues); +  else +  gc_mark_svalues(ITEM(a), a->size); +  } +  } + } +  + static void low_gc_cycle_check_array(struct array *a) + { +  int e;   #ifdef PIKE_DEBUG - INT32 gc_touch_all_arrays(void) +  if (a == &empty_array) fatal("Trying to gc cycle check empty_array.\n"); + #endif +  +  if (a->type_field & BIT_COMPLEX)    { -  INT32 n = 0; +  if (a->flags & ARRAY_WEAK_FLAG) +  gc_recurse_weak_array(a, gc_cycle_check_weak_svalues); +  else +  gc_cycle_check_svalues(ITEM(a), a->size); +  } + } +  + void real_gc_cycle_check_array(struct array *a) + { +  GC_CYCLE_ENTER(a, 0) { +  low_gc_cycle_check_array(a); +  } GC_CYCLE_LEAVE; + } +  + void real_gc_cycle_check_array_weak(struct array *a) + { +  GC_CYCLE_ENTER(a, 1) { +  low_gc_cycle_check_array(a); +  } GC_CYCLE_LEAVE; + } +  + #ifdef PIKE_DEBUG + unsigned gc_touch_all_arrays(void) + { +  unsigned n = 0;    struct array *a = &empty_array;    do {    debug_gc_touch(a);    n++; -  +  if (!a->next || a->next->prev != a) +  fatal("Error in array link list.\n");    a=a->next;    } while (a != &empty_array);    return n;   }   #endif      void gc_check_all_arrays(void)   {    struct array *a;    a=&empty_array;
pike.git/src/array.c:1840:    if(d_flag > 1) array_check_type_field(a);   #endif    gc_check_array(a);    a=a->next;    } while (a != & empty_array);   }         void gc_mark_all_arrays(void)   { -  struct array *a; -  -  a=&empty_array; -  do -  { +  gc_mark_array_pos = gc_internal_array; +  gc_mark(&empty_array); +  while (gc_mark_array_pos != &empty_array) { +  struct array *a = gc_mark_array_pos; + #ifdef PIKE_DEBUG +  if (!a) fatal("Null pointer in array list.\n"); + #endif +  gc_mark_array_pos = a->next;    if(gc_is_referenced(a))    gc_mark_array_as_referenced(a); -  +  } + }    -  a=a->next; -  } while (a != & empty_array); + void gc_cycle_check_all_arrays(void) + { +  struct array *a; +  for (a = gc_internal_array; a != &empty_array; a = a->next) { +  real_gc_cycle_check_array(a); +  run_lifo_queue(&gc_mark_queue);    } -  + }      void gc_free_all_unreferenced_arrays(void)   {    struct array *a,*next;    -  a=&empty_array; -  do +  for (a = gc_internal_array; a != &empty_array; a = next)    { -  + #ifdef PIKE_DEBUG +  if (!a) +  fatal("Null pointer in array list.\n"); + #endif    if(gc_do_free(a))    { -  add_ref(a); +  /* Got an extra ref from gc_cycle_pop(). */    free_svalues(ITEM(a), a->size, a->type_field);    a->size=0;    -  +  gc_free_extra_ref(a);    SET_NEXT_AND_FREE(a, free_array); -  -  if (!(a = next)) -  fatal("Null pointer in array list.\n"); +     } -  else if(a->flags & ARRAY_WEAK_FLAG) -  { -  int e; -  add_ref(a); -  -  if(a->flags & ARRAY_WEAK_SHRINK) -  { -  int d=0; -  for(e=0;e<a->size;e++) -  { -  if(a->item[e].type <= MAX_COMPLEX && -  !(a->item[e].type == T_OBJECT && a->item[e].u.object->prog && -  a->item[e].u.object->prog->flags & PROGRAM_NO_WEAK_FREE) && -  gc_do_free(a->item[e].u.refs)) -  free_svalue(a->item+e); +     else -  a->item[d++]=a->item[e]; -  } -  a->size=d; -  }else{ -  for(e=0;e<a->size;e++) +     { -  if(a->item[e].type <= MAX_COMPLEX && -  !(a->item[e].type == T_OBJECT && a->item[e].u.object->prog && -  a->item[e].u.object->prog->flags & PROGRAM_NO_WEAK_FREE) && -  gc_do_free(a->item[e].u.refs)) -  { -  free_svalue(a->item+e); -  a->item[e].type=T_INT; -  a->item[e].u.integer=0; -  a->item[e].subtype=NUMBER_DESTRUCTED; -  a->type_field |= BIT_INT; +  next=a->next;    }    }   }    -  SET_NEXT_AND_FREE(a, free_array); +     -  if (!(a = next)) -  fatal("Null pointer in array list.\n"); -  } -  else -  { +    #ifdef PIKE_DEBUG -  if(d_flag) gc_check_array(a); - #endif -  a=a->next; -  } -  } while (a != & empty_array); - } +     -  - #ifdef PIKE_DEBUG -  +    void debug_dump_type_field(TYPE_FIELD t)   {    int e;    for(e=0;e<=MAX_TYPE;e++)    if(t & (1<<e))    fprintf(stderr," %s",get_name_of_type(e));       for(;e<16;e++)    if(t & (1<<e))    fprintf(stderr," <%d>",e);