From ec9beed47048ea8bad7ad438581161e2f9b76b2f Mon Sep 17 00:00:00 2001 From: Danya Berezun Date: Tue, 5 Sep 2023 20:56:10 +0200 Subject: [PATCH] upd comments --- runtime/gc.h | 98 ++++++++++++++++++++++++++++------------------- runtime/runtime.c | 43 +++++++-------------- 2 files changed, 72 insertions(+), 69 deletions(-) diff --git a/runtime/gc.h b/runtime/gc.h index 0655e0f69..db765e2fc 100644 --- a/runtime/gc.h +++ b/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); diff --git a/runtime/runtime.c b/runtime/runtime.c index ca45d729f..26160b86c 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -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; }