From 97a5436c61aacdf4a8699b7da3a1fc4652b87955 Mon Sep 17 00:00:00 2001 From: slava Date: Tue, 26 Sep 2006 23:00:41 +0000 Subject: [PATCH] New code-gc primitive --- library/bootstrap/primitives.factor | 3 +- library/compiler/inference/known-words.factor | 7 ++- library/tools/memory.factor | 2 +- library/tools/memory.facts | 2 +- vm/code_gc.c | 5 +++ vm/code_gc.h | 17 +++----- vm/data_gc.c | 43 ++++++++++++------- vm/data_gc.h | 3 +- vm/primitives.c | 3 +- 9 files changed, 54 insertions(+), 31 deletions(-) diff --git a/library/bootstrap/primitives.factor b/library/bootstrap/primitives.factor index 3f3c9eb53f..7963d037ef 100644 --- a/library/bootstrap/primitives.factor +++ b/library/bootstrap/primitives.factor @@ -123,7 +123,8 @@ call { "setenv" "kernel-internals" } { "stat" "io" } { "(directory)" "io" } - { "gc" "memory" } + { "data-gc" "memory" } + { "code-gc" "memory" } { "gc-time" "memory" } { "save-image" "memory" } { "datastack" "kernel" } diff --git a/library/compiler/inference/known-words.factor b/library/compiler/inference/known-words.factor index e7f1010142..1814a80de4 100644 --- a/library/compiler/inference/known-words.factor +++ b/library/compiler/inference/known-words.factor @@ -235,7 +235,12 @@ t over set-effect-terminated? \ setenv { object fixnum } { } "infer-effect" set-word-prop \ stat { string } { object } "infer-effect" set-word-prop \ (directory) { string } { array } "infer-effect" set-word-prop -\ gc { integer object } { } "infer-effect" set-word-prop +\ data-gc { integer } { } "infer-effect" set-word-prop + +! code-gc does not declare a stack effect since it might be +! called from a compiled word which becomes unreachable during +! the course of its execution, resulting in a crash + \ gc-time { } { integer } "infer-effect" set-word-prop \ save-image { string } { } "infer-effect" set-word-prop \ exit { integer } { } "infer-effect" set-word-prop diff --git a/library/tools/memory.factor b/library/tools/memory.factor index a376003070..552ad797ae 100644 --- a/library/tools/memory.factor +++ b/library/tools/memory.factor @@ -5,7 +5,7 @@ USING: arrays errors generic hashtables io kernel kernel-internals math namespaces parser prettyprint sequences strings styles vectors words ; -: full-gc ( -- ) generations 1- f gc ; +: full-gc ( -- ) generations 1- data-gc ; ! Printing an overview of heap usage. diff --git a/library/tools/memory.facts b/library/tools/memory.facts index 86758291e0..e4f737d495 100644 --- a/library/tools/memory.facts +++ b/library/tools/memory.facts @@ -1,7 +1,7 @@ IN: memory USING: errors help test ; -HELP: gc ( n -- ) +HELP: data-gc ( n -- ) { $values { "n" "a positive integer" } } { $description "Collects all generations up to and including the " { $snippet "n" } "th generation. The nursery where new objects are allocated is generation 0, and tenured space is generation " { $snippet "g-1" } " where " { $snippet "g" } " is the value output by " { $link generations } "." } ; diff --git a/vm/code_gc.c b/vm/code_gc.c index 7ebaf327ba..b8e4a92d45 100644 --- a/vm/code_gc.c +++ b/vm/code_gc.c @@ -232,3 +232,8 @@ void primitive_code_room(void) box_unsigned_cell(heap_free_space(&compiling)); box_unsigned_cell(compiling.limit - compiling.base); } + +void primitive_code_gc(void) +{ + garbage_collection(TENURED,true); +} diff --git a/vm/code_gc.h b/vm/code_gc.h index 46f414acd2..8541f568ed 100644 --- a/vm/code_gc.h +++ b/vm/code_gc.h @@ -50,16 +50,6 @@ typedef struct typedef void (*CODE_HEAP_ITERATOR)(F_COMPILED *compiled, CELL code_start, CELL reloc_start, CELL literal_start, CELL words_start, CELL words_end); -void init_code_heap(CELL size); - -void iterate_code_heap(CODE_HEAP_ITERATOR iter); - -void collect_literals(void); - -void mark_and_sweep(CELL xt); - -void primitive_code_room(void); - INLINE void iterate_code_heap_step(F_COMPILED *compiled, CODE_HEAP_ITERATOR iter) { CELL code_start = (CELL)(compiled + 1); @@ -80,3 +70,10 @@ INLINE F_COMPILED *xt_to_compiled(CELL xt) { return (F_COMPILED *)(xt - sizeof(F_COMPILED)); } + +void init_code_heap(CELL size); +void iterate_code_heap(CODE_HEAP_ITERATOR iter); +void collect_literals(void); +void mark_and_sweep(CELL xt); +void primitive_code_room(void); +void primitive_code_gc(void); diff --git a/vm/data_gc.c b/vm/data_gc.c index 316d7e8663..4ecf4dc687 100644 --- a/vm/data_gc.c +++ b/vm/data_gc.c @@ -446,10 +446,11 @@ void reset_generations(CELL from, CELL to) clear_cards(from,to); } -void begin_gc(CELL gen) +void begin_gc(CELL gen, bool code_gc) { collecting_gen = gen; collecting_gen_start = generations[gen].base; + collecting_code = code_gc; if(gen == TENURED) { @@ -471,9 +472,9 @@ void begin_gc(CELL gen) } } -void end_gc(CELL gen) +void end_gc() { - if(gen == TENURED) + if(collecting_gen == TENURED) { /* we did a full collection; no more old-to-new pointers remain since everything @@ -483,7 +484,8 @@ void end_gc(CELL gen) now empty */ reset_generations(NURSERY,TENURED - 1); - fprintf(stderr,"*** Data GC (%ld minor, %ld cards)\n", + fprintf(stderr,"*** %s GC (%ld minor, %ld cards)\n", + collecting_code ? "Code and data" : "Data", minor_collections,cards_scanned); minor_collections = 0; cards_scanned = 0; @@ -494,13 +496,20 @@ void end_gc(CELL gen) next-oldest generation no longer has any pointers into the younger generation (the younger generation is empty!) */ - unmark_cards(gen + 1,gen + 1); + unmark_cards(collecting_gen + 1,collecting_gen + 1); /* all generations up to and including the one collected are now empty */ - reset_generations(NURSERY,gen); + reset_generations(NURSERY,collecting_gen); minor_collections++; } + + if(collecting_code) + { + /* now that all reachable code blocks have been marked, + deallocate the rest */ + free_unmarked(&compiling); + } } /* collect gen and all younger generations */ @@ -524,7 +533,7 @@ void garbage_collection(CELL gen, bool code_gc) gen++; } - begin_gc(gen); + begin_gc(gen,code_gc); /* initialize chase pointer */ scan = newspace->here; @@ -535,26 +544,30 @@ void garbage_collection(CELL gen, bool code_gc) /* collect objects referenced from older generations */ collect_cards(gen); - /* collect literal objects referenced from compiled code */ - collect_literals(); - + if(!code_gc) + { + /* if we are doing code GC, then we will copy over literals + from any code block which gets marked as live. if we are not + doing code GC, just consider all literals as roots. */ + collect_literals(); + } + while(scan < newspace->here) scan = collect_next(scan); - end_gc(gen); + end_gc(); gc_time += (current_millis() - start); } -void primitive_gc(void) +void primitive_data_gc(void) { - bool code_gc = unbox_boolean(); CELL gen = to_fixnum(dpop()); - if(gen <= NURSERY || code_gc) + if(gen <= NURSERY) gen = NURSERY; else if(gen >= TENURED) gen = TENURED; - garbage_collection(gen,code_gc); + garbage_collection(gen,false); } /* WARNING: only call this from a context where all local variables diff --git a/vm/data_gc.h b/vm/data_gc.h index c4d871780d..220851ea60 100644 --- a/vm/data_gc.h +++ b/vm/data_gc.h @@ -142,6 +142,7 @@ CELL cards_scanned; /* only meaningful during a GC */ CELL collecting_gen; CELL collecting_gen_start; +bool collecting_code; /* test if the pointer is in generation being collected, or a younger one. init_data_heap() arranges things so that the older generations are first, @@ -209,7 +210,7 @@ INLINE void* allot_object(CELL type, CELL length) void update_cards_offset(void); CELL collect_next(CELL scan); void garbage_collection(CELL gen, bool code_gc); -void primitive_gc(void); +void primitive_data_gc(void); void maybe_gc(CELL size); DLLEXPORT void simple_gc(void); void primitive_gc_time(void); diff --git a/vm/primitives.c b/vm/primitives.c index c4117e96b9..f817bc18b1 100644 --- a/vm/primitives.c +++ b/vm/primitives.c @@ -92,7 +92,8 @@ void* primitives[] = { primitive_setenv, primitive_stat, primitive_read_dir, - primitive_gc, + primitive_data_gc, + primitive_code_gc, primitive_gc_time, primitive_save_image, primitive_datastack,