GC: allocate large objects directly into tenured space
parent
4515588b98
commit
b2cb88f497
|
@ -204,7 +204,7 @@ ARTICLE: "alien-callback-gc" "Callbacks and code GC"
|
|||
"A callback consits of two parts; the callback word, which pushes the address of the callback on the stack when executed, and the callback body itself. If the callback word is redefined, removed from the dictionary using " { $link forget } ", or recompiled, the callback body will not be reclaimed by the garbage collector, since potentially C code may be holding a reference to the callback body."
|
||||
$nl
|
||||
"This is the safest approach, however it can lead to code heap leaks when repeatedly reloading code which defines callbacks. If you are " { $emphasis "completely sure" } " that no running C code is holding a reference to any callbacks, you can blow them all away:"
|
||||
{ $code "USE: alien callbacks get clear-hash code-gc" }
|
||||
{ $code "USE: alien callbacks get clear-hash gc" }
|
||||
"This will reclaim all callback bodies which are otherwise unreachable from the dictionary (that is, their associated callback words have since been redefined, recompiled or forgotten)." ;
|
||||
|
||||
ARTICLE: "alien-callback" "Calling Factor from C"
|
||||
|
|
|
@ -87,7 +87,7 @@ FUNCTION: tiny ffi_test_17 int x ;
|
|||
[ -1 indirect-test-1 ] must-fail
|
||||
|
||||
: indirect-test-2
|
||||
"int" { "int" "int" } "cdecl" alien-indirect data-gc ;
|
||||
"int" { "int" "int" } "cdecl" alien-indirect gc ;
|
||||
|
||||
{ 3 1 } [ indirect-test-2 ] must-infer-as
|
||||
|
||||
|
@ -97,7 +97,7 @@ unit-test
|
|||
|
||||
: indirect-test-3
|
||||
"int" { "int" "int" "int" "int" } "stdcall" alien-indirect
|
||||
data-gc ;
|
||||
gc ;
|
||||
|
||||
<< "f-stdcall" f "stdcall" add-library >>
|
||||
|
||||
|
@ -106,13 +106,13 @@ unit-test
|
|||
|
||||
: ffi_test_18 ( w x y z -- int )
|
||||
"int" "f-stdcall" "ffi_test_18" { "int" "int" "int" "int" }
|
||||
alien-invoke data-gc ;
|
||||
alien-invoke gc ;
|
||||
|
||||
[ 25 ] [ 2 3 4 5 ffi_test_18 ] unit-test
|
||||
|
||||
: ffi_test_19 ( x y z -- bar )
|
||||
"bar" "f-stdcall" "ffi_test_19" { "long" "long" "long" }
|
||||
alien-invoke data-gc ;
|
||||
alien-invoke gc ;
|
||||
|
||||
[ 11 6 -7 ] [
|
||||
11 6 -7 ffi_test_19 dup bar-x over bar-y rot bar-z
|
||||
|
@ -143,7 +143,7 @@ FUNCTION: void ffi_test_20 double x1, double x2, double x3,
|
|||
"void"
|
||||
f "ffi_test_31"
|
||||
{ "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" }
|
||||
alien-invoke code-gc 3 ;
|
||||
alien-invoke gc 3 ;
|
||||
|
||||
[ 3 ] [ 42 [ ] each ffi_test_31 ] unit-test
|
||||
|
||||
|
@ -312,14 +312,14 @@ FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
|
|||
|
||||
: callback-4
|
||||
"void" { } "cdecl" [ "Hello world" write ] alien-callback
|
||||
data-gc ;
|
||||
gc ;
|
||||
|
||||
[ "Hello world" ] [
|
||||
[ callback-4 callback_test_1 ] with-string-writer
|
||||
] unit-test
|
||||
|
||||
: callback-5
|
||||
"void" { } "cdecl" [ data-gc ] alien-callback ;
|
||||
"void" { } "cdecl" [ gc ] alien-callback ;
|
||||
|
||||
[ "testing" ] [
|
||||
"testing" callback-5 callback_test_1
|
||||
|
|
|
@ -640,8 +640,7 @@ define-builtin
|
|||
{ "setenv" "kernel.private" }
|
||||
{ "(exists?)" "io.files.private" }
|
||||
{ "(directory)" "io.files.private" }
|
||||
{ "data-gc" "memory" }
|
||||
{ "code-gc" "memory" }
|
||||
{ "gc" "memory" }
|
||||
{ "gc-time" "memory" }
|
||||
{ "save-image" "memory" }
|
||||
{ "save-image-and-exit" "memory" }
|
||||
|
|
|
@ -2,7 +2,7 @@ IN: compiler.tests
|
|||
USING: compiler.units kernel kernel.private memory math
|
||||
math.private tools.test math.floats.private ;
|
||||
|
||||
[ 5.0 ] [ [ 5.0 ] compile-call data-gc data-gc data-gc ] unit-test
|
||||
[ 5.0 ] [ [ 5.0 ] compile-call gc gc gc ] unit-test
|
||||
[ 2.0 3.0 ] [ 3.0 [ 2.0 swap ] compile-call ] unit-test
|
||||
|
||||
[ 1 2 3 4.0 ] [ [ 1 2 3 4.0 ] compile-call ] unit-test
|
||||
|
|
|
@ -48,7 +48,7 @@ IN: compiler.tests
|
|||
[ 4 1 3 ] [ 0 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-call ] unit-test
|
||||
[ 3 1 3 ] [ 1 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-call ] unit-test
|
||||
|
||||
[ 2 3 ] [ 1 [ { [ code-gc 1 ] [ code-gc 2 ] } dispatch 3 ] compile-call ] unit-test
|
||||
[ 2 3 ] [ 1 [ { [ gc 1 ] [ gc 2 ] } dispatch 3 ] compile-call ] unit-test
|
||||
|
||||
! Labels
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ IN: continuations.tests
|
|||
! Weird PowerPC bug.
|
||||
[ ] [
|
||||
[ "4" throw ] ignore-errors
|
||||
data-gc
|
||||
data-gc
|
||||
gc
|
||||
gc
|
||||
] unit-test
|
||||
|
||||
[ f ] [ { } kernel-error? ] unit-test
|
||||
|
|
|
@ -358,9 +358,7 @@ M: object infer-call
|
|||
|
||||
\ (directory) { string } { array } <effect> set-primitive-effect
|
||||
|
||||
\ data-gc { } { } <effect> set-primitive-effect
|
||||
|
||||
\ code-gc { } { } <effect> set-primitive-effect
|
||||
\ gc { } { } <effect> set-primitive-effect
|
||||
|
||||
\ gc-time { } { integer } <effect> set-primitive-effect
|
||||
|
||||
|
|
|
@ -37,12 +37,9 @@ HELP: instances
|
|||
{ $description "Outputs a sequence of all objects in the heap which satisfy the quotation." }
|
||||
{ $notes "This word relies on " { $link each-object } ", so in particular the garbage collector is switched off while it runs and the given quotation must not allocate too much memory." } ;
|
||||
|
||||
HELP: data-gc ( -- )
|
||||
HELP: gc ( -- )
|
||||
{ $description "Performs a full garbage collection." } ;
|
||||
|
||||
HELP: code-gc ( -- )
|
||||
{ $description "Collects all generations up to and including tenured space, and also collects the code heap." } ;
|
||||
|
||||
HELP: gc-time ( -- n )
|
||||
{ $values { "n" "a timestamp in milliseconds" } }
|
||||
{ $description "Outputs the total time spent in garbage collection during this Factor session." } ;
|
||||
|
|
|
@ -8,8 +8,6 @@ IN: memory.tests
|
|||
|
||||
: leak-loop 100 [ leak-step ] times ;
|
||||
|
||||
[ ] [ leak-step leak-step leak-step data-gc ] unit-test
|
||||
|
||||
[ ] [ leak-loop ] unit-test
|
||||
|
||||
TUPLE: testing x y z ;
|
||||
|
|
12
vm/code_gc.c
12
vm/code_gc.c
|
@ -287,16 +287,6 @@ DEFINE_PRIMITIVE(code_room)
|
|||
dpush(tag_fixnum((code_heap.segment->size) / 1024));
|
||||
}
|
||||
|
||||
void code_gc(void)
|
||||
{
|
||||
garbage_collection(TENURED,false,0);
|
||||
}
|
||||
|
||||
DEFINE_PRIMITIVE(code_gc)
|
||||
{
|
||||
code_gc();
|
||||
}
|
||||
|
||||
/* Dump all code blocks for debugging */
|
||||
void dump_heap(F_HEAP *heap)
|
||||
{
|
||||
|
@ -444,7 +434,7 @@ critical here */
|
|||
void compact_code_heap(void)
|
||||
{
|
||||
/* Free all unreachable code blocks */
|
||||
code_gc();
|
||||
gc();
|
||||
|
||||
fprintf(stderr,"*** Code heap compaction...\n");
|
||||
fflush(stderr);
|
||||
|
|
|
@ -85,8 +85,6 @@ void iterate_code_heap(CODE_HEAP_ITERATOR iter);
|
|||
void collect_literals(void);
|
||||
void recursive_mark(F_BLOCK *block);
|
||||
void dump_heap(F_HEAP *heap);
|
||||
void code_gc(void);
|
||||
void compact_code_heap(void);
|
||||
|
||||
DECLARE_PRIMITIVE(code_room);
|
||||
DECLARE_PRIMITIVE(code_gc);
|
||||
|
|
|
@ -224,7 +224,7 @@ CELL allot_code_block(CELL size)
|
|||
/* If allocation failed, do a code GC */
|
||||
if(start == 0)
|
||||
{
|
||||
code_gc();
|
||||
gc();
|
||||
start = heap_allot(&code_heap,size);
|
||||
|
||||
/* Insufficient room even after code GC, give up */
|
||||
|
|
73
vm/data_gc.c
73
vm/data_gc.c
|
@ -1,8 +1,6 @@
|
|||
#include "master.h"
|
||||
|
||||
#define GC_DEBUG 0
|
||||
|
||||
#define ALLOC_DATA_HEAP "alloc_data_heap: gens=%ld, young_size=%ld, aging_size=%ld\n"
|
||||
#define ALLOC_DATA_HEAP "alloc_data_heap: gens=%ld, young_size=%ld, aging_size=%ld, tenured_size=%ld\n"
|
||||
#define GC_REQUESTED "garbage_collection: growing_data_heap=%d, requested_bytes=%ld\n"
|
||||
#define BEGIN_GC "begin_gc: growing_data_heap=%d, collecting_gen=%ld\n"
|
||||
#define END_GC "end_gc: gc_elapsed=%ld\n"
|
||||
|
@ -31,25 +29,28 @@ void init_cards_offset(void)
|
|||
|
||||
F_DATA_HEAP *alloc_data_heap(CELL gens,
|
||||
CELL young_size,
|
||||
CELL aging_size)
|
||||
CELL aging_size,
|
||||
CELL tenured_size)
|
||||
{
|
||||
GC_PRINT(ALLOC_DATA_HEAP,gens,young_size,aging_size);
|
||||
GC_PRINT(ALLOC_DATA_HEAP,gens,young_size,aging_size,tenured_size);
|
||||
|
||||
young_size = align_page(young_size);
|
||||
aging_size = align_page(aging_size);
|
||||
tenured_size = align_page(tenured_size);
|
||||
|
||||
F_DATA_HEAP *data_heap = safe_malloc(sizeof(F_DATA_HEAP));
|
||||
data_heap->young_size = young_size;
|
||||
data_heap->aging_size = aging_size;
|
||||
data_heap->tenured_size = tenured_size;
|
||||
data_heap->gen_count = gens;
|
||||
|
||||
CELL total_size;
|
||||
if(data_heap->gen_count == 1)
|
||||
total_size = 2 * aging_size;
|
||||
total_size = 2 * tenured_size;
|
||||
else if(data_heap->gen_count == 2)
|
||||
total_size = (gens - 1) * young_size + 2 * aging_size;
|
||||
total_size = young_size + 2 * tenured_size;
|
||||
else if(data_heap->gen_count == 3)
|
||||
total_size = gens * young_size + 2 * aging_size;
|
||||
total_size = young_size + 2 * aging_size + 2 * tenured_size;
|
||||
else
|
||||
{
|
||||
fatal_error("Invalid number of generations",data_heap->gen_count);
|
||||
|
@ -58,8 +59,8 @@ F_DATA_HEAP *alloc_data_heap(CELL gens,
|
|||
|
||||
data_heap->segment = alloc_segment(total_size);
|
||||
|
||||
data_heap->generations = safe_malloc(sizeof(F_ZONE) * gens);
|
||||
data_heap->semispaces = safe_malloc(sizeof(F_ZONE) * gens);
|
||||
data_heap->generations = safe_malloc(sizeof(F_ZONE) * data_heap->gen_count);
|
||||
data_heap->semispaces = safe_malloc(sizeof(F_ZONE) * data_heap->gen_count);
|
||||
|
||||
CELL cards_size = total_size / CARD_SIZE;
|
||||
data_heap->cards = safe_malloc(cards_size);
|
||||
|
@ -67,31 +68,19 @@ F_DATA_HEAP *alloc_data_heap(CELL gens,
|
|||
|
||||
CELL alloter = data_heap->segment->start;
|
||||
|
||||
alloter = init_zone(&data_heap->semispaces[NURSERY],0,alloter);
|
||||
alloter = init_zone(&data_heap->generations[TENURED],tenured_size,alloter);
|
||||
alloter = init_zone(&data_heap->semispaces[TENURED],tenured_size,alloter);
|
||||
|
||||
alloter = init_zone(&data_heap->generations[TENURED],aging_size,alloter);
|
||||
alloter = init_zone(&data_heap->semispaces[TENURED],aging_size,alloter);
|
||||
|
||||
int i;
|
||||
|
||||
if(data_heap->gen_count > 2)
|
||||
if(data_heap->gen_count == 3)
|
||||
{
|
||||
alloter = init_zone(&data_heap->generations[AGING],young_size,alloter);
|
||||
alloter = init_zone(&data_heap->semispaces[AGING],young_size,alloter);
|
||||
|
||||
for(i = gens - 3; i >= 0; i--)
|
||||
{
|
||||
alloter = init_zone(&data_heap->generations[i],
|
||||
young_size,alloter);
|
||||
}
|
||||
alloter = init_zone(&data_heap->generations[AGING],aging_size,alloter);
|
||||
alloter = init_zone(&data_heap->semispaces[AGING],aging_size,alloter);
|
||||
}
|
||||
else
|
||||
|
||||
if(data_heap->gen_count >= 2)
|
||||
{
|
||||
for(i = gens - 2; i >= 0; i--)
|
||||
{
|
||||
alloter = init_zone(&data_heap->generations[i],
|
||||
young_size,alloter);
|
||||
}
|
||||
alloter = init_zone(&data_heap->generations[NURSERY],young_size,alloter);
|
||||
alloter = init_zone(&data_heap->semispaces[NURSERY],0,alloter);
|
||||
}
|
||||
|
||||
if(alloter != data_heap->segment->end)
|
||||
|
@ -104,10 +93,12 @@ F_DATA_HEAP *grow_data_heap(F_DATA_HEAP *data_heap, CELL requested_bytes)
|
|||
{
|
||||
CELL new_young_size = (data_heap->young_size * 2) + requested_bytes;
|
||||
CELL new_aging_size = (data_heap->aging_size * 2) + requested_bytes;
|
||||
CELL new_tenured_size = (data_heap->tenured_size * 2) + requested_bytes;
|
||||
|
||||
return alloc_data_heap(data_heap->gen_count,
|
||||
new_young_size,
|
||||
new_aging_size);
|
||||
new_aging_size,
|
||||
new_tenured_size);
|
||||
}
|
||||
|
||||
void dealloc_data_heap(F_DATA_HEAP *data_heap)
|
||||
|
@ -141,9 +132,10 @@ void set_data_heap(F_DATA_HEAP *data_heap_)
|
|||
void init_data_heap(CELL gens,
|
||||
CELL young_size,
|
||||
CELL aging_size,
|
||||
CELL tenured_size,
|
||||
bool secure_gc_)
|
||||
{
|
||||
set_data_heap(alloc_data_heap(gens,young_size,aging_size));
|
||||
set_data_heap(alloc_data_heap(gens,young_size,aging_size,tenured_size));
|
||||
|
||||
gc_locals_region = alloc_segment(getpagesize());
|
||||
gc_locals = gc_locals_region->start - CELLS;
|
||||
|
@ -258,7 +250,7 @@ void begin_scan(void)
|
|||
|
||||
DEFINE_PRIMITIVE(begin_scan)
|
||||
{
|
||||
data_gc();
|
||||
gc();
|
||||
begin_scan();
|
||||
}
|
||||
|
||||
|
@ -645,7 +637,7 @@ void begin_gc(CELL requested_bytes)
|
|||
printf("Newspace: ");
|
||||
dump_zone(newspace);
|
||||
printf("\n");
|
||||
#endif;
|
||||
#endif
|
||||
}
|
||||
|
||||
void end_gc(void)
|
||||
|
@ -788,14 +780,14 @@ void garbage_collection(CELL gen,
|
|||
performing_gc = false;
|
||||
}
|
||||
|
||||
void data_gc(void)
|
||||
void gc(void)
|
||||
{
|
||||
garbage_collection(TENURED,false,0);
|
||||
}
|
||||
|
||||
DEFINE_PRIMITIVE(data_gc)
|
||||
DEFINE_PRIMITIVE(gc)
|
||||
{
|
||||
data_gc();
|
||||
gc();
|
||||
}
|
||||
|
||||
/* Push total time spent on GC */
|
||||
|
@ -806,7 +798,8 @@ DEFINE_PRIMITIVE(gc_time)
|
|||
|
||||
void simple_gc(void)
|
||||
{
|
||||
maybe_gc(0);
|
||||
if(nursery->here + ALLOT_BUFFER_ZONE > nursery->end)
|
||||
garbage_collection(NURSERY,false,0);
|
||||
}
|
||||
|
||||
DEFINE_PRIMITIVE(become)
|
||||
|
@ -828,5 +821,5 @@ DEFINE_PRIMITIVE(become)
|
|||
forward_object(old_obj,new_obj);
|
||||
}
|
||||
|
||||
data_gc();
|
||||
gc();
|
||||
}
|
||||
|
|
81
vm/data_gc.h
81
vm/data_gc.h
|
@ -19,6 +19,8 @@ DECLARE_PRIMITIVE(begin_scan);
|
|||
DECLARE_PRIMITIVE(next_object);
|
||||
DECLARE_PRIMITIVE(end_scan);
|
||||
|
||||
void gc(void);
|
||||
|
||||
/* generational copying GC divides memory into zones */
|
||||
typedef struct {
|
||||
/* allocation pointer is 'here'; its offset is hardcoded in the
|
||||
|
@ -34,6 +36,7 @@ typedef struct {
|
|||
|
||||
CELL young_size;
|
||||
CELL aging_size;
|
||||
CELL tenured_size;
|
||||
|
||||
CELL gen_count;
|
||||
|
||||
|
@ -134,6 +137,7 @@ CELL init_zone(F_ZONE *z, CELL size, CELL base);
|
|||
void init_data_heap(CELL gens,
|
||||
CELL young_size,
|
||||
CELL aging_size,
|
||||
CELL tenured_size,
|
||||
bool secure_gc_);
|
||||
|
||||
/* statistics */
|
||||
|
@ -186,10 +190,7 @@ INLINE void do_slots(CELL obj, void (* iter)(CELL *))
|
|||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
so we have to check that the pointer occurs after the beginning of
|
||||
the requested generation. */
|
||||
/* test if the pointer is in generation being collected, or a younger one. */
|
||||
INLINE bool should_copy(CELL untagged)
|
||||
{
|
||||
if(in_zone(newspace,untagged))
|
||||
|
@ -306,37 +307,53 @@ allocation (which does not call GC because of possible roots in volatile
|
|||
registers) does not run out of memory */
|
||||
#define ALLOT_BUFFER_ZONE 1024
|
||||
|
||||
#define SUFFICIENT_ROOM(a) (nursery->here + ALLOT_BUFFER_ZONE + a <= nursery->end)
|
||||
|
||||
INLINE void maybe_gc(CELL a)
|
||||
{
|
||||
/* If there is enough room, return */
|
||||
if(SUFFICIENT_ROOM(a))
|
||||
return;
|
||||
/* If the object is bigger than the nursery, grow immediately */
|
||||
else if(nursery->size - ALLOT_BUFFER_ZONE <= a)
|
||||
garbage_collection(TENURED,true,a);
|
||||
/* Otherwise, collect the nursery */
|
||||
else
|
||||
{
|
||||
garbage_collection(NURSERY,false,0);
|
||||
|
||||
/* If there is still insufficient room, try growing the heap.
|
||||
This can only happen if the number of generations is 1. */
|
||||
if(SUFFICIENT_ROOM(a)) return;
|
||||
|
||||
garbage_collection(TENURED,true,a);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* It is up to the caller to fill in the object's fields in a meaningful
|
||||
* fashion!
|
||||
*/
|
||||
INLINE void* allot_object(CELL type, CELL length)
|
||||
INLINE void* allot_object(CELL type, CELL a)
|
||||
{
|
||||
maybe_gc(length);
|
||||
CELL* object = allot_zone(nursery,length);
|
||||
CELL *object;
|
||||
|
||||
/* If the object is bigger than the nursery, allocate it in
|
||||
tenured space */
|
||||
if(nursery->size - ALLOT_BUFFER_ZONE > a)
|
||||
{
|
||||
/* If there is insufficient room, collect the nursery */
|
||||
if(nursery->here + ALLOT_BUFFER_ZONE + a > nursery->end)
|
||||
garbage_collection(NURSERY,false,0);
|
||||
|
||||
object = allot_zone(nursery,a);
|
||||
}
|
||||
else
|
||||
{
|
||||
F_ZONE *tenured = &data_heap->generations[TENURED];
|
||||
|
||||
/* If tenured space does not have enough room, collect */
|
||||
if(tenured->here + a > tenured->end)
|
||||
{
|
||||
gc();
|
||||
tenured = &data_heap->generations[TENURED];
|
||||
}
|
||||
|
||||
/* If it still won't fit, grow the heap */
|
||||
if(tenured->here + a > tenured->end)
|
||||
{
|
||||
garbage_collection(TENURED,true,a);
|
||||
tenured = &data_heap->generations[TENURED];
|
||||
}
|
||||
|
||||
object = allot_zone(tenured,a);
|
||||
|
||||
/* We have to do this */
|
||||
allot_barrier((CELL)object);
|
||||
|
||||
/* Allows initialization code to store old->new pointers
|
||||
without hitting the write barrier in the common case of
|
||||
a nursery allocation */
|
||||
write_barrier((CELL)object);
|
||||
}
|
||||
|
||||
*object = tag_header(type);
|
||||
return object;
|
||||
}
|
||||
|
@ -345,8 +362,6 @@ CELL collect_next(CELL scan);
|
|||
|
||||
DLLEXPORT void simple_gc(void);
|
||||
|
||||
void data_gc(void);
|
||||
|
||||
DECLARE_PRIMITIVE(data_gc);
|
||||
DECLARE_PRIMITIVE(gc);
|
||||
DECLARE_PRIMITIVE(gc_time);
|
||||
DECLARE_PRIMITIVE(become);
|
||||
|
|
|
@ -246,7 +246,7 @@ void dump_generations(void)
|
|||
|
||||
void dump_objects(F_FIXNUM type)
|
||||
{
|
||||
data_gc();
|
||||
gc();
|
||||
begin_scan();
|
||||
|
||||
CELL obj;
|
||||
|
|
10
vm/factor.c
10
vm/factor.c
|
@ -13,15 +13,17 @@ void default_parameters(F_PARAMETERS *p)
|
|||
p->gen_count = 2;
|
||||
p->code_size = 4;
|
||||
p->young_size = 1;
|
||||
p->aging_size = 6;
|
||||
p->aging_size = 1;
|
||||
p->tenured_size = 6;
|
||||
#else
|
||||
p->ds_size = 32 * CELLS;
|
||||
p->rs_size = 32 * CELLS;
|
||||
|
||||
p->gen_count = 3;
|
||||
p->code_size = 8 * CELLS;
|
||||
p->young_size = 2 * CELLS;
|
||||
p->aging_size = 4 * CELLS;
|
||||
p->young_size = 2;
|
||||
p->aging_size = 2;
|
||||
p->tenured_size = 4 * CELLS;
|
||||
#endif
|
||||
|
||||
p->secure_gc = false;
|
||||
|
@ -84,6 +86,7 @@ void init_factor(F_PARAMETERS *p)
|
|||
/* Megabytes */
|
||||
p->young_size <<= 20;
|
||||
p->aging_size <<= 20;
|
||||
p->tenured_size <<= 20;
|
||||
p->code_size <<= 20;
|
||||
|
||||
/* Disable GC during init as a sanity check */
|
||||
|
@ -153,6 +156,7 @@ void init_factor_from_args(F_CHAR *image, int argc, F_CHAR **argv, bool embedded
|
|||
else if(factor_arg(argv[i],STR_FORMAT("-generations=%d"),&p.gen_count));
|
||||
else if(factor_arg(argv[i],STR_FORMAT("-young=%d"),&p.young_size));
|
||||
else if(factor_arg(argv[i],STR_FORMAT("-aging=%d"),&p.aging_size));
|
||||
else if(factor_arg(argv[i],STR_FORMAT("-tenured=%d"),&p.tenured_size));
|
||||
else if(factor_arg(argv[i],STR_FORMAT("-codeheap=%d"),&p.code_size));
|
||||
else if(STRCMP(argv[i],STR_FORMAT("-securegc")) == 0)
|
||||
p.secure_gc = true;
|
||||
|
|
12
vm/image.c
12
vm/image.c
|
@ -17,10 +17,14 @@ INLINE void load_data_heap(FILE *file, F_HEADER *h, F_PARAMETERS *p)
|
|||
{
|
||||
CELL good_size = h->data_size + (1 << 20);
|
||||
|
||||
if(good_size > p->aging_size)
|
||||
p->aging_size = good_size;
|
||||
if(good_size > p->tenured_size)
|
||||
p->tenured_size = good_size;
|
||||
|
||||
init_data_heap(p->gen_count,p->young_size,p->aging_size,p->secure_gc);
|
||||
init_data_heap(p->gen_count,
|
||||
p->young_size,
|
||||
p->aging_size,
|
||||
p->tenured_size,
|
||||
p->secure_gc);
|
||||
|
||||
F_ZONE *tenured = &data_heap->generations[TENURED];
|
||||
|
||||
|
@ -145,7 +149,7 @@ void save_image(const F_CHAR *filename)
|
|||
DEFINE_PRIMITIVE(save_image)
|
||||
{
|
||||
/* do a full GC to push everything into tenured space */
|
||||
code_gc();
|
||||
gc();
|
||||
|
||||
save_image(unbox_native_string());
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
const F_CHAR* image;
|
||||
CELL ds_size, rs_size;
|
||||
CELL gen_count, young_size, aging_size;
|
||||
CELL gen_count, young_size, aging_size, tenured_size;
|
||||
CELL code_size;
|
||||
bool secure_gc;
|
||||
bool fep;
|
||||
|
|
|
@ -90,8 +90,7 @@ void *primitives[] = {
|
|||
primitive_setenv,
|
||||
primitive_existsp,
|
||||
primitive_read_dir,
|
||||
primitive_data_gc,
|
||||
primitive_code_gc,
|
||||
primitive_gc,
|
||||
primitive_gc_time,
|
||||
primitive_save_image,
|
||||
primitive_save_image_and_exit,
|
||||
|
|
|
@ -57,10 +57,9 @@ void set_profiling(bool profiling)
|
|||
|
||||
profiling_p = profiling;
|
||||
|
||||
/* Push everything to tenured space so that we can heap scan,
|
||||
also code GC so that we can allocate profiling blocks if
|
||||
necessary */
|
||||
code_gc();
|
||||
/* Push everything to tenured space so that we can heap scan
|
||||
and allocate profiling blocks if necessary */
|
||||
gc();
|
||||
|
||||
/* Update word XTs and saved callstack objects */
|
||||
begin_scan();
|
||||
|
|
Loading…
Reference in New Issue