diff --git a/src/array.c b/src/array.c index 88237a175e8e906b39eecc25f4d0906f5374404b..b5dc886fb85f370a55f94a1f5afbeda9714dfab9 100644 --- a/src/array.c +++ b/src/array.c @@ -27,7 +27,6 @@ struct array empty_array= 0, /* malloced Size = 0 */ 0, /* no types */ T_MIXED, /* mixed array */ - 0, /* no flags */ }; @@ -61,7 +60,6 @@ struct array *low_allocate_array(INT32 size,INT32 extra_space) v->malloced_size=size+extra_space; v->size=size; - v->flags=0; v->refs=1; v->prev=&empty_array; v->next=empty_array.next; @@ -1286,69 +1284,64 @@ void check_all_arrays() #ifdef GC2 -void gc_check_array(struct array *a) +void gc_mark_array_as_referenced(struct array *a) { - if(a == gc_ptr) gc_refs++; - if(a->flags & GC_MARK) return; - a->flags |= GC_MARK; - if(!(a->type_field & BIT_COMPLEX)) return; - gc_check_svalues(ITEM(a), a->size); + if(gc_mark(a)) + if(a->type_field & BIT_COMPLEX) + gc_mark_svalues(ITEM(a), a->size); } - void gc_check_all_arrays() { - struct array *a,*n; - + struct array *a; a=&empty_array; do { - if(!(a->flags & GC_MARK) && a->type_field & BIT_COMPLEX) - { - gc_ptr=a; - gc_refs=0; - - gc_check_array(a); - - a->refs++; - - if(gc_refs == a->refs) - { - /* This structure contains as many references to itself as - * it has referenes, which means that it is circular and - * should be destroyed, so please go away. - */ - - free_svalues(ITEM(a), a->size, a->type_field); - - a->size=0; - - } - - if(!(n=a->next)) - fatal("Null pointer in array list.\n"); - - free_array(a); - a=n; - }else{ - a=a->next; - } + if(a->type_field & BIT_COMPLEX) + gc_check_svalues(ITEM(a), a->size); + + a=a->next; } while (a != & empty_array); } -void gc_clear_array_marks() + +void gc_mark_all_arrays() { struct array *a; a=&empty_array; do { - a->flags &=~ GC_MARK; + if(gc_is_referenced(a)) + gc_mark_array_as_referenced(a); + a=a->next; - } while (a != & empty_array); } +void gc_free_all_unreferenced_arrays() +{ + struct array *a,*next; + + a=&empty_array; + do + { + if(gc_do_free(a)) + { + a->refs++; + free_svalues(ITEM(a), a->size, a->type_field); + a->size=0; + + if(!(next=a->next)) + fatal("Null pointer in array list.\n"); + + free_array(a); + a=next; + }else{ + a=a->next; + } + } while (a != & empty_array); +} #endif /* GC2 */ diff --git a/src/array.h b/src/array.h index a0a058021fe3dcb413cf160fe71e71f5c4c84f5d..526120e763bb0347544710534ecf42c3ebe2020f 100644 --- a/src/array.h +++ b/src/array.h @@ -20,11 +20,12 @@ struct array * Bits can be set that don't exist in the array * though. */ - INT16 flags; /* flags, like gc_cycle */ struct svalue item[1]; }; +extern struct array empty_array; + #define ITEM(X) ((X)->item) /* These are arguments for the function 'merge' which merges two sorted @@ -120,9 +121,10 @@ void array_replace(struct array *a, struct svalue *to); void check_array(struct array *a); void check_all_arrays(); -void gc_check_array(struct array *a); +void gc_mark_array_as_referenced(struct array *a); void gc_check_all_arrays(); -void gc_clear_array_marks(); +void gc_mark_all_arrays(); +void gc_free_all_unreferenced_arrays(); /* Prototypes end here */ diff --git a/src/gc.c b/src/gc.c index d4f1cf812d7640d458615d891acda4241f40e0ee..4e86c01b2e992b6c653a31c03353e4f0ccc057ab 100644 --- a/src/gc.c +++ b/src/gc.c @@ -7,6 +7,13 @@ #include "global.h" #ifdef GC2 + +#include "array.h" +#include "list.h" +#include "mapping.h" +#include "object.h" +#include "program.h" + #include "gc.h" #include "main.h" @@ -17,10 +24,10 @@ #define GC_CONST 20 #define MIN_ALLOC_THRESHOLD 1000 +#defien MAX_ALLOC_THRESHOLD 10000000 #define MULTIPLIER 0.9 +#define MARKER_CHUNK_SIZE 1023 -void *gc_ptr; -INT32 gc_refs; INT32 num_objects; INT32 num_allocs; INT32 alloc_threshold = MIN_ALLOC_THRESHOLD; @@ -28,10 +35,143 @@ INT32 alloc_threshold = MIN_ALLOC_THRESHOLD; static double objects_alloced; static double objects_freed; +#define GC_REFERENCED 1 + +struct marker +{ + struct marker *next; + void *marked; + INT32 refs; + INT32 flags; +}; + +struct marker_chunk +{ + struct marker_chunk *next; + struct marker markers[MARKER_CHUNK_SIZE]; +}; + +static struct marker_chunk *chunk=0; +static int markers_left_in_chunk=0; + +static struct marker *new_marker() +{ + if(!markers_left_in_chunk) + { + struct marker_chunk *m; + m=(struct marker_chunk *)xalloc(sizeof(struct marker_chunk)); + m->next=chunk; + chunk=m; + markers_left_in_chunk=MARKER_CHUNK_SIZE; + } + markers_left_in_chunk--; + + return chunk->markers + markers_left_in_chunk; +} + +static struct marker **hash=0; +static int hashsize=0; + +static struct marker *getmark(void *a) +{ + int hashval; + struct marker *m; + + hashval=((long)a)%hashsize; + + for(m=hash[hashval];m;m=m->next) + if(m->marked == a) + return m; + + m=new_marker(); + m->marked=a; + m->refs=0; + m->flags=0; + m->next=hash[hashval]; + hash[hashval]=m; + + return m; +} + +void gc_check(void *a) +{ + getmark(a)->refs++; +} + +int gc_is_referenced(void *a) +{ + struct marker *m; + m=getmark(a); +#ifdef DEBUG + if(m->refs > *(INT32 *)a) + fatal("Ref counts are totally wrong!!!\n"); +#endif + return m->refs < *(INT32 *)a; +} + +int gc_mark(void *a) +{ + struct marker *m; + m=getmark(a); + + if(m->flags & GC_REFERENCED) + { + return 0; + }else{ + m->flags |= GC_REFERENCED; + return 1; + } +} + +int gc_do_free(void *a) +{ + struct marker *m; + m=getmark(a); + return !(m->flags & GC_REFERENCED); +} + +/* Not all of these are primes, but they should be adequate */ +static INT32 hashprimes[] = +{ + 31, /* ~ 2^0 = 1 */ + 31, /* ~ 2^1 = 2 */ + 31, /* ~ 2^2 = 4 */ + 31, /* ~ 2^3 = 8 */ + 31, /* ~ 2^4 = 16 */ + 31, /* ~ 2^5 = 32 */ + 61, /* ~ 2^6 = 64 */ + 127, /* ~ 2^7 = 128 */ + 251, /* ~ 2^8 = 256 */ + 541, /* ~ 2^9 = 512 */ + 1151, /* ~ 2^10 = 1024 */ + 2111, /* ~ 2^11 = 2048 */ + 4327, /* ~ 2^12 = 4096 */ + 8803, /* ~ 2^13 = 8192 */ + 17903, /* ~ 2^14 = 16384 */ + 32321, /* ~ 2^15 = 32768 */ + 65599, /* ~ 2^16 = 65536 */ + 133153, /* ~ 2^17 = 131072 */ + 270001, /* ~ 2^18 = 264144 */ + 547453, /* ~ 2^19 = 524288 */ + 1109891, /* ~ 2^20 = 1048576 */ + 2000143, /* ~ 2^21 = 2097152 */ + 4561877, /* ~ 2^22 = 4194304 */ + 9248339, /* ~ 2^23 = 8388608 */ + 16777215, /* ~ 2^24 = 16777216 */ + 33554431, /* ~ 2^25 = 33554432 */ + 67108863, /* ~ 2^26 = 67108864 */ + 134217727, /* ~ 2^27 = 134217728 */ + 268435455, /* ~ 2^28 = 268435456 */ + 536870911, /* ~ 2^29 = 536870912 */ + 1073741823,/* ~ 2^30 = 1073741824 */ + 2147483647,/* ~ 2^31 = 2147483648 */ +}; + void do_gc() { double tmp; INT32 tmp2; + struct marker_chunk *m; tmp2=num_objects; @@ -45,14 +185,45 @@ void do_gc() objects_freed*=MULTIPLIER; objects_freed += (double) num_objects; - - gc_clear_array_marks(); - gc_clear_object_marks(); - gc_clear_program_marks(); + + + /* init hash , hashsize will be a prime between num_objects/8 and + * num_objects/4, this will assure that no re-hashing is needed. + */ + hashsize=my_log2(num_objects); + hashsize-=2; + if(hashsize<0) hashsize=0; + hashsize=hashprimes[hashsize]; + hash=(struct marker **)xalloc(sizeof(struct marker **)*hashsize); + MEMSET((char *)hash,0,sizeof(struct marker **)*hashsize); + markers_left_in_chunk=0; gc_check_all_arrays(); + gc_check_all_lists(); + gc_check_all_mappings(); gc_check_all_programs(); gc_check_all_objects(); + + gc_mark_all_arrays(); + gc_mark_all_lists(); + gc_mark_all_mappings(); + gc_mark_all_programs(); + gc_mark_all_objects(); + + gc_free_all_unreferenced_arrays(); + gc_free_all_unreferenced_lists(); + gc_free_all_unreferenced_mappings(); + gc_free_all_unreferenced_programs(); + gc_free_all_unreferenced_objects(); + + + /* Free hash table */ + free((char *)hash); + while(m=chunk) + { + chunk=m->next; + free((char *)m); + } objects_freed -= (double) num_objects; @@ -76,14 +247,6 @@ void do_gc() (long)(tmp2-num_objects),(long)tmp2); #endif } -#endif - - - - - - - - +#endif diff --git a/src/gc.h b/src/gc.h index 96746616ea256836fadab7f71b2dad092f349115..cffbd118c245a927357070cdb2cd4071af049bf6 100644 --- a/src/gc.h +++ b/src/gc.h @@ -5,15 +5,12 @@ #include "types.h" -extern void *gc_ptr; -extern INT32 gc_refs; extern INT32 num_objects; extern INT32 num_allocs; extern INT32 alloc_threshold; #define GC_ALLOC() do{ num_objects++; if(++num_allocs > alloc_threshold) do_gc(); } while(0); #define GC_FREE() num_objects-- -#define GC_MARK 1 #else @@ -24,6 +21,12 @@ extern INT32 alloc_threshold; #endif /* Prototypes begin here */ +struct marker; +struct marker_chunk; +void gc_check(void *a); +int gc_is_referenced(void *a); +int gc_mark(void *a); +int gc_do_free(void *a); void do_gc(); /* Prototypes end here */ diff --git a/src/list.c b/src/list.c index c2a968482e2861846a9d3448e53f36de49ddcac3..8975acc4645ee39a3556555bd6156810a67b4a44 100644 --- a/src/list.c +++ b/src/list.c @@ -14,6 +14,7 @@ #include "dynamic_buffer.h" #include "interpret.h" #include "builtin_efuns.h" +#include "gc.h" struct list *first_list; @@ -28,6 +29,7 @@ int list_member(struct list *l, struct svalue *ind) static struct list *allocate_list(struct array *ind) { struct list *l; + GC_ALLOC(); l=ALLOC_STRUCT(list); l->next = first_list; l->prev = 0; @@ -56,6 +58,7 @@ void really_free_list(struct list *l) if(first_list == l) first_list = 0; free((char *)l); + GC_FREE(); } static void order_list(struct list *l) @@ -247,7 +250,7 @@ struct list *copy_list_recursively(struct list *l, } } - ret=allocate_list(0); + ret=allocate_list( & empty_array ); doing.pointer_b=(void *)ret; ret->ind=copy_array_recursively(l->ind,&doing); @@ -256,3 +259,49 @@ struct list *copy_list_recursively(struct list *l, return ret; } + + +#ifdef GC2 + +void gc_mark_list_as_referenced(struct list *l) +{ + if(gc_mark(l)) + gc_mark_array_as_referenced(l->ind); +} + +void gc_check_all_lists() +{ + struct list *l; + for(l=first_list;l;l=l->next) + gc_check(l->ind); +} + +void gc_mark_all_lists() +{ + struct list *l; + for(l=first_list;l;l=l->next) + if(gc_is_referenced(l)) + gc_mark_list_as_referenced(l); +} + +void gc_free_all_unreferenced_lists() +{ + struct list *l,*next; + + for(l=first_list;l;l=next) + { + if(gc_do_free(l)) + { + l->refs++; + free_svalues(ITEM(l->ind), l->ind->size, l->ind->type_field); + l->ind->size=0; + next=l->next; + + free_list(l); + }else{ + next=l->next; + } + } +} + +#endif /* GC2 */ diff --git a/src/list.h b/src/list.h index da66aaee93295d90456dfbf9e9d79755cc97908e..e072f0af66ac65748b1846d8d6db2815ca7941b5 100644 --- a/src/list.h +++ b/src/list.h @@ -37,6 +37,10 @@ node * make_node_from_list(struct list *l); void f_aggregate_list(INT32 args); struct list *copy_list_recursively(struct list *l, struct processing *p); +void gc_mark_list_as_referenced(struct list *l); +void gc_check_all_lists(); +void gc_mark_all_lists(); +void gc_free_all_unreferenced_lists(); /* Prototypes end here */ #endif diff --git a/src/mapping.c b/src/mapping.c index b23d2bdff5355ca6e7f97728164d7932547e0f35..5f566a0cc8e6be3ef444452412bbf60b07097d52 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -14,6 +14,7 @@ #include "memory.h" #include "dynamic_buffer.h" #include "interpret.h" +#include "gc.h" struct mapping *first_mapping; @@ -67,6 +68,7 @@ void mapping_index(struct svalue *dest, static struct mapping *allocate_mapping(struct array *ind, struct array *val) { struct mapping *m; + GC_ALLOC(); m=ALLOC_STRUCT(mapping); m->next = first_mapping; m->prev = 0; @@ -97,6 +99,8 @@ void really_free_mapping(struct mapping *m) if(first_mapping == m) first_mapping = 0; free((char *)m); + + GC_FREE(); } static void order_mapping(struct mapping *m) @@ -369,7 +373,7 @@ struct mapping *copy_mapping_recursively(struct mapping *m, } } - ret=allocate_mapping(0,0); + ret=allocate_mapping(&empty_array, &empty_array); doing.pointer_b=(void *)ret; ret->ind=copy_array_recursively(m->ind,&doing); @@ -436,3 +440,57 @@ void check_all_mappings() check_mapping(m); } #endif + + +#ifdef GC2 + +void gc_mark_mapping_as_referenced(struct mapping *m) +{ + if(gc_mark(m)) + { + gc_mark_array_as_referenced(m->ind); + gc_mark_array_as_referenced(m->val); + } +} + +void gc_check_all_mappings() +{ + struct mapping *m; + for(m=first_mapping;m;m=m->next) + { + gc_check(m->ind); + gc_check(m->val); + } +} + +void gc_mark_all_mappings() +{ + struct mapping *m; + for(m=first_mapping;m;m=m->next) + if(gc_is_referenced(m)) + gc_mark_mapping_as_referenced(m); +} + +void gc_free_all_unreferenced_mappings() +{ + struct mapping *m,*next; + + for(m=first_mapping;m;m=next) + { + if(gc_do_free(m)) + { + m->refs++; + free_svalues(ITEM(m->ind), m->ind->size, m->ind->type_field); + free_svalues(ITEM(m->val), m->val->size, m->val->type_field); + m->ind->size=0; + m->val->size=0; + next=m->next; + + free_mapping(m); + }else{ + next=m->next; + } + } +} + +#endif /* GC2 */ diff --git a/src/mapping.h b/src/mapping.h index 8eb88ae8732822dc959257a27dc4e08e5ad00f81..8132d4cae5edcb581ac7b681d93bcc31d20076e7 100644 --- a/src/mapping.h +++ b/src/mapping.h @@ -55,5 +55,9 @@ void mapping_search_no_free(struct svalue *to, struct svalue *start); void check_mapping(struct mapping *m); void check_all_mappings(); +void gc_mark_mapping_as_referenced(struct mapping *m); +void gc_check_all_mappings(); +void gc_mark_all_mappings(); +void gc_free_all_unreferenced_mappings(); /* Prototypes end here */ #endif diff --git a/src/object.c b/src/object.c index 86174658e9593168b002d1de02bcc8480135464f..e61c203dcda7ebfc683bb3b6b2d761078f66c8ce 100644 --- a/src/object.c +++ b/src/object.c @@ -644,45 +644,83 @@ struct array *object_values(struct object *o) void gc_check_object(struct object *o) { - INT32 e; - if(o == gc_ptr) gc_refs++; - if(o->flags & GC_MARK) return; - o->flags |= GC_MARK; - - if(!o->prog) return; +} - for(e=0;e<(int)o->prog->num_identifier_indexes;e++) +void gc_mark_object_as_referenced(struct object *o) +{ + if(gc_mark(o)) { - struct identifier *i; - - i=ID_FROM_INT(o->prog, e); - - if(i->flags & IDENTIFIER_FUNCTION) continue; - - if(i->run_time_type == T_MIXED) + if(o->prog) { - gc_check_svalues((struct svalue *)LOW_GET_GLOBAL(o,e,i),1); - }else{ - gc_check_short_svalue((union anything *)LOW_GET_GLOBAL(o,e,i), - i->run_time_type); + INT32 e; + + for(e=0;e<(int)o->prog->num_identifier_indexes;e++) + { + struct identifier *i; + + i=ID_FROM_INT(o->prog, e); + + if(i->flags & IDENTIFIER_FUNCTION) continue; + + if(i->run_time_type == T_MIXED) + { + gc_mark_svalues((struct svalue *)LOW_GET_GLOBAL(o,e,i),1); + }else{ + gc_mark_short_svalue((union anything *)LOW_GET_GLOBAL(o,e,i), + i->run_time_type); + } + } } } } void gc_check_all_objects() { - struct object *o, *next; + struct object *o; + for(o=first_object;o;o=o->next) + { + if(o->prog) + { + INT32 e; + + for(e=0;e<(int)o->prog->num_identifier_indexes;e++) + { + struct identifier *i; + + i=ID_FROM_INT(o->prog, e); + + if(i->flags & IDENTIFIER_FUNCTION) continue; + + if(i->run_time_type == T_MIXED) + { + gc_check_svalues((struct svalue *)LOW_GET_GLOBAL(o,e,i),1); + }else{ + gc_check_short_svalue((union anything *)LOW_GET_GLOBAL(o,e,i), + i->run_time_type); + } + } + } + } +} + +void gc_mark_all_objects() +{ + struct object *o; + for(o=first_object;o;o=o->next) + if(gc_is_referenced(o)) + gc_mark_object_as_referenced(o); +} + +void gc_free_all_unreferenced_objects() +{ + struct object *o,*next; + for(o=first_object;o;o=next) { - if(!(o->flags & GC_MARK)) + if(gc_do_free(o)) { - gc_ptr=o; - gc_refs=0; - o->refs++; - - if(gc_refs == o->refs) destruct(o); - + destruct(o); next=o->next; free_object(o); }else{ @@ -691,11 +729,5 @@ void gc_check_all_objects() } } -void gc_clear_object_marks() -{ - struct object *o; - - for(o=first_object;o;o=o->next) o->flags &=~ GC_MARK; -} - #endif /* GC2 */ + diff --git a/src/object.h b/src/object.h index 32608e56ed1024f3e9f0caa00ee2d7c8b3802238..e4bb8cd0dd2360cfa1c55991163221e03b387bde 100644 --- a/src/object.h +++ b/src/object.h @@ -14,9 +14,6 @@ struct object { INT32 refs; /* Reference count, must be first. */ -#ifdef GC2 - INT16 flags; -#endif struct program *prog; struct object *next; struct object *prev; @@ -63,8 +60,10 @@ void cleanup_objects(); struct array *object_indices(struct object *o); struct array *object_values(struct object *o); void gc_check_object(struct object *o); +void gc_mark_object_as_referenced(struct object *o); void gc_check_all_objects(); -void gc_clear_object_marks(); +void gc_mark_all_objects(); +void gc_free_all_unreferenced_objects(); /* Prototypes end here */ #endif /* OBJECT_H */ diff --git a/src/program.c b/src/program.c index 85de0f4f961d7ac359d02faba3b4d28f4c29ceba..ec2f5f944259d07834406a11384213eb70d021e2 100644 --- a/src/program.c +++ b/src/program.c @@ -1303,31 +1303,37 @@ void cleanup_program() #ifdef GC2 -void gc_check_program(struct program *p) +void gc_mark_program_as_referenced(struct program *p) { - if(p==gc_ptr) gc_refs++; - if(p->flags & GC_MARK) return; - p->flags |= GC_MARK; - gc_check_svalues(p->constants, p->num_constants); + if(gc_mark(p)) + gc_mark_svalues(p->constants, p->num_constants); } void gc_check_all_programs() { - struct program *p, *next; + struct program *p; + for(p=first_program;p;p=p->next) + gc_check_svalues(p->constants, p->num_constants); +} + +void gc_mark_all_programs() +{ + struct program *p; + for(p=first_program;p;p=p->next) + if(gc_is_referenced(p)) + gc_mark_program_as_referenced(p); +} + +void gc_free_all_unreferenced_programs() +{ + struct program *p,*next; + for(p=first_program;p;p=next) { - if(!(p->flags & GC_MARK)) + if(gc_do_free(p)) { - gc_ptr=p; - gc_refs=0; - - gc_check_program(p); - p->refs++; - - if(gc_refs == p->refs) - free_svalues(p->constants, p->num_constants, -1); - + free_svalues(p->constants, p->num_constants, -1); next=p->next; free_program(p); }else{ @@ -1336,11 +1342,4 @@ void gc_check_all_programs() } } -void gc_clear_program_marks() -{ - struct program *p; - - for(p=first_program;p;p=p->next) p->flags &=~ GC_MARK; -} - #endif /* GC2 */ diff --git a/src/program.h b/src/program.h index fe1c265aab35c35d732104281544b06c8e80ae27..b8a8fed9fdd4d7274050be83c7dc76048338f5a1 100644 --- a/src/program.h +++ b/src/program.h @@ -93,7 +93,6 @@ struct inherit struct program { INT32 refs; - INT32 flags; INT32 id; /* used to identify program in caches */ INT32 storage_needed; /* storage needed in the object struct */ @@ -182,9 +181,10 @@ struct program *end_c_program(char *name); void add_function(char *name,void (*cfun)(INT32),char *type,INT16 flags); void check_all_programs(); void cleanup_program(); -void gc_check_program(struct program *p); +void gc_mark_program_as_referenced(struct program *p); void gc_check_all_programs(); -void gc_clear_program_marks(); +void gc_mark_all_programs(); +void gc_free_all_unreferenced_programs(); /* Prototypes end here */ diff --git a/src/svalue.c b/src/svalue.c index 6793c90527bf8e231fe64010267aa287e77d3ff1..58b8d82b81637dbeb145fdad58929d88552686e0 100644 --- a/src/svalue.c +++ b/src/svalue.c @@ -641,23 +641,24 @@ void gc_check_svalues(struct svalue *s, int num) { switch(s->type) { - case T_ARRAY: gc_check_array(s->u.array); break; - case T_LIST: - gc_check_array(s->u.list->ind); - break; - case T_MAPPING: - gc_check_array(s->u.mapping->ind); - gc_check_array(s->u.mapping->val); - break; + case T_FUNCTION: + if(s->subtype == -1) break; + case T_OBJECT: if(s->u.object->prog) { - gc_check_object(s->u.object); + gc_check(s->u.object); }else{ free_svalue(s); } break; - case T_PROGRAM: gc_check_program(s->u.program); break; + + case T_PROGRAM: + case T_ARRAY: + case T_LIST: + case T_MAPPING: + gc_check(s->u.refs); + break; } } } @@ -667,21 +668,69 @@ void gc_check_short_svalue(union anything *u, TYPE_T type) if(!u->refs) return; switch(type) { - case T_ARRAY: gc_check_array(u->array); break; - case T_LIST: gc_check_array(u->list->ind); break; + case T_OBJECT: + if(u->object->prog) + { + gc_check(u->object); + }else{ + free_short_svalue(u,T_OBJECT); + } + break; + + case T_ARRAY: + case T_LIST: case T_MAPPING: - gc_check_array(u->mapping->ind); - gc_check_array(u->mapping->val); + case T_PROGRAM: + gc_check(u->refs); break; + } +} + +void gc_mark_svalues(struct svalue *s, int num) +{ + INT32 e; + for(e=0;e<num;e++,s++) + { + switch(s->type) + { + case T_ARRAY: gc_mark_array_as_referenced(s->u.array); break; + case T_LIST: gc_mark_list_as_referenced(s->u.list); break; + case T_MAPPING: gc_mark_mapping_as_referenced(s->u.mapping); break; + case T_PROGRAM: gc_mark_program_as_referenced(s->u.program); break; + + case T_FUNCTION: + if(s->subtype == -1) break; + + case T_OBJECT: + if(s->u.object->prog) + { + gc_mark_object_as_referenced(s->u.object); + }else{ + free_svalue(s); + } + break; + } + } +} + +void gc_mark_short_svalue(union anything *u, TYPE_T type) +{ + if(!u->refs) return; + switch(type) + { + case T_ARRAY: gc_mark_array_as_referenced(u->array); break; + case T_LIST: gc_mark_list_as_referenced(u->list); break; + case T_MAPPING: gc_mark_mapping_as_referenced(u->mapping); break; + case T_PROGRAM: gc_mark_program_as_referenced(u->program); break; + case T_OBJECT: if(u->object->prog) { - gc_check_object(u->object); + gc_mark_object_as_referenced(u->object); }else{ free_short_svalue(u,T_OBJECT); } break; - case T_PROGRAM: gc_check_program(u->program); break; } } #endif /* GC2 */