mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-05 22:38:44 +00:00
upd comments
This commit is contained in:
parent
20cb055883
commit
ec9beed470
2 changed files with 72 additions and 69 deletions
98
runtime/gc.h
98
runtime/gc.h
|
|
@ -9,12 +9,14 @@
|
|||
#define MAKE_ENQUEUED(x) (x = (((int)(x)) | 2))
|
||||
#define MAKE_DEQUEUED(x) (x = (((int)(x)) & (~2)))
|
||||
#define RESET_MARK_BIT(x) (x = (((int)(x)) & (~1)))
|
||||
#define GET_FORWARD_ADDRESS(x) \
|
||||
(((size_t)(x)) \
|
||||
& (~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)
|
||||
#define SET_FORWARD_ADDRESS(x, addr) \
|
||||
(x = ((x & 3) | ((int)(addr)))) // take the last two bits as they are and make all others zero
|
||||
#define EXTRA_ROOM_HEAP_COEFFICIENT 2 // TODO: tune this parameter
|
||||
// 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)
|
||||
#define GET_FORWARD_ADDRESS(x) (((size_t)(x)) & (~3))
|
||||
// take the last two bits as they are and make all others zero
|
||||
#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
|
||||
# define MINIMUM_HEAP_CAPACITY (8)
|
||||
#else
|
||||
|
|
@ -31,13 +33,12 @@ typedef struct {
|
|||
} heap_iterator;
|
||||
|
||||
typedef struct {
|
||||
// holds type of object, which fields we are iterating over
|
||||
lama_type type;
|
||||
// here a pointer to the object header is stored
|
||||
void *obj_ptr;
|
||||
void *cur_field;
|
||||
lama_type type; // holds type of object, which fields we are iterating over
|
||||
void *obj_ptr; // place to store a pointer to the object header
|
||||
void *cur_field;
|
||||
} obj_field_iterator;
|
||||
|
||||
// Memory pool for linear memory allocation
|
||||
typedef struct {
|
||||
size_t *begin;
|
||||
size_t *end;
|
||||
|
|
@ -45,14 +46,6 @@ typedef struct {
|
|||
size_t size;
|
||||
} 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
|
||||
// allocates object of the given size on the heap
|
||||
void *alloc(size_t);
|
||||
|
|
@ -79,31 +72,56 @@ size_t compute_locations ();
|
|||
void update_references (memory_chunk *);
|
||||
void physically_relocate (memory_chunk *);
|
||||
|
||||
// written in ASM
|
||||
extern void __gc_init (
|
||||
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 (
|
||||
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 __shutdown (
|
||||
void); // mostly useful for tests but basically you want to call this in case you want to deallocate all object allocated via GC
|
||||
// written in ASM
|
||||
// ============================================================================
|
||||
// GC extra roots
|
||||
// ============================================================================
|
||||
// Lama's program stack is continuous, i.e. it never interleaves with runtime
|
||||
// function's activation records. But some valid Lama's pointers can escape
|
||||
// into runtime. Those values (theirs stack addresses) has to be registered in
|
||||
// an auxiliary data structure called `extra_roots_pool`.
|
||||
// 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);
|
||||
// written in ASM
|
||||
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);
|
||||
bool is_valid_heap_pointer (const size_t *);
|
||||
static inline bool is_valid_pointer (const size_t *);
|
||||
|
||||
void clear_extra_roots (void);
|
||||
|
||||
void push_extra_root (void **p);
|
||||
|
||||
void pop_extra_root (void **p);
|
||||
|
||||
/* Functions for tests */
|
||||
|
||||
// ============================================================================
|
||||
// Auxiliary functions for tests
|
||||
// ============================================================================
|
||||
#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,
|
||||
// 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)
|
||||
void set_extra_roots (size_t extra_roots_size, void **extra_roots_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
// ============================================================================
|
||||
// Utility functions
|
||||
// ============================================================================
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
|
||||
// Compare sexprs tags
|
||||
// Compare s-exprs tags
|
||||
extern int LcompareTags (void *p, void *q) {
|
||||
data *pd, *qd;
|
||||
|
||||
|
|
@ -111,8 +111,8 @@ extern int LcompareTags (void *p, void *q) {
|
|||
} else {
|
||||
failure("not a sexpr in compareTags: %d, %d\n", TAG(pd->data_header), TAG(qd->data_header));
|
||||
}
|
||||
|
||||
return 0; // never happens
|
||||
// dead code
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Functional synonym for built-in operator ":";
|
||||
|
|
@ -1165,17 +1165,15 @@ extern void *Lfread (char *fname) {
|
|||
|
||||
f = fopen(fname, "r");
|
||||
|
||||
if (f) {
|
||||
if (fseek(f, 0l, SEEK_END) >= 0) {
|
||||
long size = ftell(f);
|
||||
void *s = LmakeString(BOX(size));
|
||||
if (f && fseek(f, 0l, SEEK_END) >= 0) {
|
||||
long size = ftell(f);
|
||||
void *s = LmakeString(BOX(size));
|
||||
|
||||
rewind(f);
|
||||
rewind(f);
|
||||
|
||||
if (fread(s, 1, size, f) == size) {
|
||||
fclose(f);
|
||||
return s;
|
||||
}
|
||||
if (fread(s, 1, size, f) == size) {
|
||||
fclose(f);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1190,16 +1188,11 @@ extern void Lfwrite (char *fname, char *contents) {
|
|||
|
||||
f = fopen(fname, "w");
|
||||
|
||||
if (f) {
|
||||
if (fprintf(f, "%s", contents) < 0)
|
||||
;
|
||||
else {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
if (f && !(fprintf(f, "%s", contents) < 0)) {
|
||||
fclose(f);
|
||||
} else {
|
||||
failure("fwrite (\"%s\"): %s\n", fname, strerror(errno));
|
||||
}
|
||||
|
||||
failure("fwrite (\"%s\"): %s\n", fname, strerror(errno));
|
||||
}
|
||||
|
||||
extern void *Lfexists (char *fname) {
|
||||
|
|
@ -1287,11 +1280,3 @@ extern void set_args (int argc, char *argv[]) {
|
|||
|
||||
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