mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 06:48:48 +00:00
upd comments
This commit is contained in:
parent
20cb055883
commit
ec9beed470
2 changed files with 72 additions and 69 deletions
96
runtime/gc.h
96
runtime/gc.h
|
|
@ -9,12 +9,14 @@
|
||||||
#define MAKE_ENQUEUED(x) (x = (((int)(x)) | 2))
|
#define MAKE_ENQUEUED(x) (x = (((int)(x)) | 2))
|
||||||
#define MAKE_DEQUEUED(x) (x = (((int)(x)) & (~2)))
|
#define MAKE_DEQUEUED(x) (x = (((int)(x)) & (~2)))
|
||||||
#define RESET_MARK_BIT(x) (x = (((int)(x)) & (~1)))
|
#define RESET_MARK_BIT(x) (x = (((int)(x)) & (~1)))
|
||||||
#define GET_FORWARD_ADDRESS(x) \
|
// since last 2 bits are used for mark-bit and enqueued-bit and due to correct
|
||||||
(((size_t)(x)) \
|
// alignment we can expect that last 2 bits don't influence address (they
|
||||||
& (~3)) // since last 2 bits are used for mark-bit and enqueued-bit and due to correct alignment we can expect that last 2 bits don't influence address (they should always be zero)
|
// should always be zero)
|
||||||
#define SET_FORWARD_ADDRESS(x, addr) \
|
#define GET_FORWARD_ADDRESS(x) (((size_t)(x)) & (~3))
|
||||||
(x = ((x & 3) | ((int)(addr)))) // take the last two bits as they are and make all others zero
|
// take the last two bits as they are and make all others zero
|
||||||
#define EXTRA_ROOM_HEAP_COEFFICIENT 2 // TODO: tune this parameter
|
#define SET_FORWARD_ADDRESS(x, addr) (x = ((x & 3) | ((int)(addr))))
|
||||||
|
// if heap is full after gc shows in how many times it has to be extended
|
||||||
|
#define EXTRA_ROOM_HEAP_COEFFICIENT 2
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
# define MINIMUM_HEAP_CAPACITY (8)
|
# define MINIMUM_HEAP_CAPACITY (8)
|
||||||
#else
|
#else
|
||||||
|
|
@ -31,13 +33,12 @@ typedef struct {
|
||||||
} heap_iterator;
|
} heap_iterator;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// holds type of object, which fields we are iterating over
|
lama_type type; // holds type of object, which fields we are iterating over
|
||||||
lama_type type;
|
void *obj_ptr; // place to store a pointer to the object header
|
||||||
// here a pointer to the object header is stored
|
|
||||||
void *obj_ptr;
|
|
||||||
void *cur_field;
|
void *cur_field;
|
||||||
} obj_field_iterator;
|
} obj_field_iterator;
|
||||||
|
|
||||||
|
// Memory pool for linear memory allocation
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t *begin;
|
size_t *begin;
|
||||||
size_t *end;
|
size_t *end;
|
||||||
|
|
@ -45,14 +46,6 @@ typedef struct {
|
||||||
size_t size;
|
size_t size;
|
||||||
} memory_chunk;
|
} memory_chunk;
|
||||||
|
|
||||||
/* GC extra roots */
|
|
||||||
#define MAX_EXTRA_ROOTS_NUMBER 32
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int current_free;
|
|
||||||
void **roots[MAX_EXTRA_ROOTS_NUMBER];
|
|
||||||
} extra_roots_pool;
|
|
||||||
|
|
||||||
// the only GC-related function that should be exposed, others are useful for tests and internal implementation
|
// the only GC-related function that should be exposed, others are useful for tests and internal implementation
|
||||||
// allocates object of the given size on the heap
|
// allocates object of the given size on the heap
|
||||||
void *alloc(size_t);
|
void *alloc(size_t);
|
||||||
|
|
@ -79,31 +72,56 @@ size_t compute_locations ();
|
||||||
void update_references (memory_chunk *);
|
void update_references (memory_chunk *);
|
||||||
void physically_relocate (memory_chunk *);
|
void physically_relocate (memory_chunk *);
|
||||||
|
|
||||||
// written in ASM
|
// ============================================================================
|
||||||
extern void __gc_init (
|
// GC extra roots
|
||||||
void); // MANDATORY TO CALL BEFORE ANY INTERACTION WITH GC (apart from cases where we are working with virtual stack as happens in tests)
|
// ============================================================================
|
||||||
extern void __init (
|
// Lama's program stack is continuous, i.e. it never interleaves with runtime
|
||||||
void); // should be called before interaction with GC in case of using in tests with virtual stack, otherwise it is automatically invoked by __gc_init
|
// function's activation records. But some valid Lama's pointers can escape
|
||||||
extern void __shutdown (
|
// into runtime. Those values (theirs stack addresses) has to be registered in
|
||||||
void); // mostly useful for tests but basically you want to call this in case you want to deallocate all object allocated via GC
|
// an auxiliary data structure called `extra_roots_pool`.
|
||||||
// written in ASM
|
// extra_roots_pool is a simple LIFO stack. During `pop` it compares that pop's
|
||||||
|
// argument is equal to the current stack top.
|
||||||
|
#define MAX_EXTRA_ROOTS_NUMBER 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int current_free;
|
||||||
|
void **roots[MAX_EXTRA_ROOTS_NUMBER];
|
||||||
|
} extra_roots_pool;
|
||||||
|
|
||||||
|
void clear_extra_roots (void);
|
||||||
|
void push_extra_root (void **p);
|
||||||
|
void pop_extra_root (void **p);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Implemented in GASM: see gc_runtime.s
|
||||||
|
// ============================================================================
|
||||||
|
// MANDATORY TO CALL BEFORE ANY INTERACTION WITH GC (apart from cases where we
|
||||||
|
// are working with virtual stack as happens in tests)
|
||||||
|
extern void __gc_init (void);
|
||||||
|
// should be called before interaction with GC in case of using in tests with
|
||||||
|
// virtual stack, otherwise it is automatically invoked by `__gc_init`
|
||||||
|
extern void __init (void);
|
||||||
|
// mostly useful for tests but basically you want to call this in case you want
|
||||||
|
// to deallocate all object allocated via GC
|
||||||
|
extern void __shutdown (void);
|
||||||
|
// Next two functions sets and unsets `__gc_stack_top`
|
||||||
|
// The first (`__pre_gc`) should be called in the very beginning of any runtime
|
||||||
|
// function during the execution of which garbage collection can be initiated.
|
||||||
|
// The last one is a `companion function` which has to be called at the very
|
||||||
|
// end of any function that called `__prec_gc`
|
||||||
extern void __pre_gc (void);
|
extern void __pre_gc (void);
|
||||||
// written in ASM
|
|
||||||
extern void __post_gc (void);
|
extern void __post_gc (void);
|
||||||
|
|
||||||
// invoked from ASM
|
// ============================================================================
|
||||||
|
// invoked from GASM: see gc_runtime.s
|
||||||
|
// ============================================================================
|
||||||
extern void gc_test_and_mark_root (size_t **root);
|
extern void gc_test_and_mark_root (size_t **root);
|
||||||
bool is_valid_heap_pointer (const size_t *);
|
bool is_valid_heap_pointer (const size_t *);
|
||||||
static inline bool is_valid_pointer (const size_t *);
|
static inline bool is_valid_pointer (const size_t *);
|
||||||
|
|
||||||
void clear_extra_roots (void);
|
// ============================================================================
|
||||||
|
// Auxiliary functions for tests
|
||||||
void push_extra_root (void **p);
|
// ============================================================================
|
||||||
|
|
||||||
void pop_extra_root (void **p);
|
|
||||||
|
|
||||||
/* Functions for tests */
|
|
||||||
|
|
||||||
#if defined(FULL_INVARIANT_CHECKS) && defined(DEBUG_VERSION)
|
#if defined(FULL_INVARIANT_CHECKS) && defined(DEBUG_VERSION)
|
||||||
// makes a snapshot of current objects in heap (both alive and dead), writes these ids to object_ids_buf,
|
// makes a snapshot of current objects in heap (both alive and dead), writes these ids to object_ids_buf,
|
||||||
// returns number of ids dumped
|
// returns number of ids dumped
|
||||||
|
|
@ -118,11 +136,11 @@ void set_stack (size_t stack_top, size_t stack_bottom);
|
||||||
|
|
||||||
// function to mock extra roots (Lama specific)
|
// function to mock extra roots (Lama specific)
|
||||||
void set_extra_roots (size_t extra_roots_size, void **extra_roots_ptr);
|
void set_extra_roots (size_t extra_roots_size, void **extra_roots_ptr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Utility functions */
|
// ============================================================================
|
||||||
|
// Utility functions
|
||||||
|
// ============================================================================
|
||||||
// accepts pointer to the start of the region and to the end of the region
|
// accepts pointer to the start of the region and to the end of the region
|
||||||
// scans it and if it meets a pointer, it should be modified in according to forward address
|
// scans it and if it meets a pointer, it should be modified in according to forward address
|
||||||
void scan_and_fix_region (memory_chunk *old_heap, void *start, void *end);
|
void scan_and_fix_region (memory_chunk *old_heap, void *start, void *end);
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ extern int LkindOf (void *p) {
|
||||||
return TAG(TO_DATA(p)->data_header);
|
return TAG(TO_DATA(p)->data_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare sexprs tags
|
// Compare s-exprs tags
|
||||||
extern int LcompareTags (void *p, void *q) {
|
extern int LcompareTags (void *p, void *q) {
|
||||||
data *pd, *qd;
|
data *pd, *qd;
|
||||||
|
|
||||||
|
|
@ -111,8 +111,8 @@ extern int LcompareTags (void *p, void *q) {
|
||||||
} else {
|
} else {
|
||||||
failure("not a sexpr in compareTags: %d, %d\n", TAG(pd->data_header), TAG(qd->data_header));
|
failure("not a sexpr in compareTags: %d, %d\n", TAG(pd->data_header), TAG(qd->data_header));
|
||||||
}
|
}
|
||||||
|
// dead code
|
||||||
return 0; // never happens
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functional synonym for built-in operator ":";
|
// Functional synonym for built-in operator ":";
|
||||||
|
|
@ -1165,8 +1165,7 @@ extern void *Lfread (char *fname) {
|
||||||
|
|
||||||
f = fopen(fname, "r");
|
f = fopen(fname, "r");
|
||||||
|
|
||||||
if (f) {
|
if (f && fseek(f, 0l, SEEK_END) >= 0) {
|
||||||
if (fseek(f, 0l, SEEK_END) >= 0) {
|
|
||||||
long size = ftell(f);
|
long size = ftell(f);
|
||||||
void *s = LmakeString(BOX(size));
|
void *s = LmakeString(BOX(size));
|
||||||
|
|
||||||
|
|
@ -1177,7 +1176,6 @@ extern void *Lfread (char *fname) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
failure("fread (\"%s\"): %s\n", fname, strerror(errno));
|
failure("fread (\"%s\"): %s\n", fname, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
@ -1190,16 +1188,11 @@ extern void Lfwrite (char *fname, char *contents) {
|
||||||
|
|
||||||
f = fopen(fname, "w");
|
f = fopen(fname, "w");
|
||||||
|
|
||||||
if (f) {
|
if (f && !(fprintf(f, "%s", contents) < 0)) {
|
||||||
if (fprintf(f, "%s", contents) < 0)
|
|
||||||
;
|
|
||||||
else {
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
failure("fwrite (\"%s\"): %s\n", fname, strerror(errno));
|
failure("fwrite (\"%s\"): %s\n", fname, strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void *Lfexists (char *fname) {
|
extern void *Lfexists (char *fname) {
|
||||||
|
|
@ -1287,11 +1280,3 @@ extern void set_args (int argc, char *argv[]) {
|
||||||
|
|
||||||
push_extra_root((void **)&global_sysargs);
|
push_extra_root((void **)&global_sysargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GC starts here */
|
|
||||||
|
|
||||||
static int enable_GC = 1;
|
|
||||||
|
|
||||||
extern void LenableGC () { enable_GC = 1; }
|
|
||||||
|
|
||||||
extern void LdisableGC () { enable_GC = 0; }
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue