mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 06:48:48 +00:00
Added check of invariance of objects' topology before and after compaction
This commit is contained in:
parent
11d496405b
commit
31551e73fd
5 changed files with 112 additions and 16 deletions
|
|
@ -1,11 +1,11 @@
|
|||
CC=gcc
|
||||
FLAGS=-m32 -g2 -fstack-protector-all
|
||||
FLAGS=-m32 -g2 -fstack-protector-all -DFULL_INVARIANT_CHECKS
|
||||
|
||||
all: gc_runtime.o gc.o runtime.o
|
||||
ar rc runtime.a gc_runtime.o runtime.o gc.o
|
||||
|
||||
test.o: gc.c gc.h gc_runtime.s runtime.c runtime.h runtime_common.h virt_stack.c virt_stack.h test_main.c test_util.s
|
||||
$(CC) -o test.o -DDEBUG_VERSION $(FLAGS) gc.c gc_runtime.s virt_stack.c runtime.c test_main.c test_util.s
|
||||
$(CC) -o test.o -DDEBUG_VERSION $(FLAGS) gc.c gc_runtime.s virt_stack.c ext_arr.c runtime.c test_main.c test_util.s
|
||||
|
||||
virt_stack.o: virt_stack.h virt_stack.c
|
||||
$(CC) $(FLAGS) -c virt_stack.c
|
||||
|
|
|
|||
113
runtime/gc.c
113
runtime/gc.c
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
static const size_t INIT_HEAP_SIZE = MINIMUM_HEAP_CAPACITY;
|
||||
|
||||
#ifdef DEBUG_VERSION
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
size_t cur_id = 0;
|
||||
#endif
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ void handler (int sig) {
|
|||
}
|
||||
|
||||
void *alloc (size_t size) {
|
||||
#ifdef DEBUG_VERSION
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
++cur_id;
|
||||
#endif
|
||||
size = BYTES_TO_WORDS(size);
|
||||
|
|
@ -61,6 +61,83 @@ void *alloc (size_t size) {
|
|||
return p;
|
||||
}
|
||||
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
|
||||
// precondition: obj_content is a valid address pointing to the content of an object
|
||||
static void objects_dfs(FILE *f, void *obj_content) {
|
||||
void *obj_header = get_obj_header_ptr(obj_content);
|
||||
data *obj_data = TO_DATA(obj_content);
|
||||
// internal mark-bit for this dfs, should be recovered by the caller
|
||||
if ((obj_data->forward_address & 2) != 0) {
|
||||
return;
|
||||
}
|
||||
// set this bit as 1
|
||||
obj_data->forward_address |= 2;
|
||||
fprintf(f, "%zu ", obj_data->id);
|
||||
// first cycle: print object's fields
|
||||
for (obj_field_iterator field_it = ptr_field_begin_iterator(obj_header);
|
||||
!field_is_done_iterator(&field_it);
|
||||
obj_next_field_iterator(&field_it)) {
|
||||
size_t field_value = *(size_t *) field_it.cur_field;
|
||||
if (is_valid_heap_pointer((size_t *) field_value)) {
|
||||
fprintf(f, "%zu ", TO_DATA(field_value)->id);
|
||||
} else {
|
||||
fprintf(f, "%d ", UNBOX(field_value));
|
||||
}
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
for (obj_field_iterator field_it = ptr_field_begin_iterator(obj_header);
|
||||
!field_is_done_iterator(&field_it);
|
||||
obj_next_field_iterator(&field_it)) {
|
||||
size_t field_value = *(size_t *) field_it.cur_field;
|
||||
if (is_valid_heap_pointer((size_t *) field_value)) {
|
||||
objects_dfs(f, (void*) field_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FILE *print_objects_traversal(bool marked) {
|
||||
FILE *f = tmpfile();
|
||||
for (heap_iterator it = heap_begin_iterator();
|
||||
!heap_is_done_iterator(&it);
|
||||
heap_next_obj_iterator(&it)) {
|
||||
void *obj_header = it.current;
|
||||
data *obj_data = TO_DATA(get_object_content_ptr(obj_header));
|
||||
if ((obj_data->forward_address & 1) == marked) {
|
||||
objects_dfs(f, get_object_content_ptr(obj_header));
|
||||
}
|
||||
}
|
||||
|
||||
// resetting bit that represent mark-bit for this internal dfs-traversal
|
||||
for (heap_iterator it = heap_begin_iterator();
|
||||
!heap_is_done_iterator(&it);
|
||||
heap_next_obj_iterator(&it)) {
|
||||
void *obj_header = it.current;
|
||||
data *obj_data = TO_DATA(get_object_content_ptr(obj_header));
|
||||
obj_data->forward_address &= (~2);
|
||||
}
|
||||
}
|
||||
|
||||
int files_cmp(FILE *f1, FILE *f2) {
|
||||
int symbol1, symbol2;
|
||||
int position = 0;
|
||||
|
||||
while ((symbol1 = fgetc(f1)) != EOF && (symbol2 = fgetc(f2)) != EOF) {
|
||||
if (symbol1 != symbol2) {
|
||||
return position;
|
||||
}
|
||||
++position;
|
||||
}
|
||||
|
||||
if (symbol1 != EOF || symbol2 != EOF) {
|
||||
return position;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void *gc_alloc_on_existing_heap (size_t size) {
|
||||
if (heap.current + size <= heap.end) {
|
||||
void *p = (void *)heap.current;
|
||||
|
|
@ -73,8 +150,23 @@ void *gc_alloc_on_existing_heap (size_t size) {
|
|||
|
||||
void *gc_alloc (size_t size) {
|
||||
mark_phase();
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
FILE *heap_before_compaction = print_objects_traversal(1);
|
||||
#endif
|
||||
|
||||
compact_phase(size);
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
FILE *heap_after_compaction = print_objects_traversal(0);
|
||||
|
||||
int pos = files_cmp(heap_before_compaction, heap_after_compaction);
|
||||
if (pos >= 0) { // position of difference is found
|
||||
fprintf(stderr, "GC invariant is broken\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fclose(heap_before_compaction);
|
||||
fclose(heap_after_compaction);
|
||||
#endif
|
||||
|
||||
return gc_alloc_on_existing_heap(size);
|
||||
}
|
||||
|
|
@ -112,13 +204,13 @@ void compact_phase (size_t additional_size) {
|
|||
update_references(&old_heap);
|
||||
physically_relocate(&old_heap);
|
||||
|
||||
// shrink it if possible, otherwise this code won'test_small_tree_compaction do anything, in both cases references
|
||||
// shrink it if possible, otherwise this code won't do anything, in both cases references
|
||||
// will remain valid
|
||||
heap.begin = mremap(
|
||||
heap.begin,
|
||||
WORDS_TO_BYTES(heap.size),
|
||||
WORDS_TO_BYTES(next_heap_size),
|
||||
0 // in this case we don't set MREMAP_MAYMOVE because it shouldn'test_small_tree_compaction move :)
|
||||
0 // in this case we don't set MREMAP_MAYMOVE because it shouldn't move :)
|
||||
);
|
||||
if (heap.begin == MAP_FAILED) {
|
||||
perror("ERROR: compact_phase: mremap failed\n");
|
||||
|
|
@ -268,7 +360,7 @@ void mark (void *obj) {
|
|||
// while the queue is non-empty
|
||||
void *cur_obj = queue_dequeue(&q_head_iter);
|
||||
mark_object(cur_obj);
|
||||
void *header_ptr = get_obj_header_ptr(cur_obj, get_type_row_ptr(cur_obj));
|
||||
void *header_ptr = get_obj_header_ptr(cur_obj);
|
||||
for (obj_field_iterator ptr_field_it = ptr_field_begin_iterator(header_ptr);
|
||||
!field_is_done_iterator(&ptr_field_it);
|
||||
obj_next_ptr_field_iterator(&ptr_field_it)) {
|
||||
|
|
@ -559,7 +651,10 @@ bool field_is_done_iterator (obj_field_iterator *it) {
|
|||
return it->cur_field >= get_end_of_obj(it->obj_ptr);
|
||||
}
|
||||
|
||||
void *get_obj_header_ptr (void *ptr, lama_type type) { return ptr - get_header_size(type); }
|
||||
void *get_obj_header_ptr (void *ptr) {
|
||||
lama_type type = get_type_row_ptr(ptr);
|
||||
return ptr - get_header_size(type);
|
||||
}
|
||||
|
||||
void *get_object_content_ptr (void *header_ptr) {
|
||||
lama_type type = get_type_header_ptr(header_ptr);
|
||||
|
|
@ -595,7 +690,7 @@ void *alloc_string (int len) {
|
|||
void *alloc_array (int len) {
|
||||
data *obj = alloc(array_size(len));
|
||||
obj->data_header = ARRAY_TAG | (len << 3);
|
||||
#ifdef DEBUG_VERSION
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
obj->id = cur_id;
|
||||
#endif
|
||||
obj->forward_address = 0;
|
||||
|
|
@ -605,7 +700,7 @@ void *alloc_array (int len) {
|
|||
void *alloc_sexp (int members) {
|
||||
sexp *obj = alloc(sexp_size(members));
|
||||
obj->sexp_header = obj->contents.data_header = SEXP_TAG | (members << 3);
|
||||
#ifdef DEBUG_VERSION
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
obj->contents.id = cur_id;
|
||||
#endif
|
||||
obj->contents.forward_address = 0;
|
||||
|
|
@ -616,7 +711,7 @@ void *alloc_sexp (int members) {
|
|||
void *alloc_closure (int captured) {
|
||||
data *obj = alloc(closure_size(captured));
|
||||
obj->data_header = CLOSURE_TAG | (captured << 3);
|
||||
#ifdef DEBUG_VERSION
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
obj->id = cur_id;
|
||||
#endif
|
||||
obj->forward_address = 0;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#ifdef DEBUG_VERSION
|
||||
# define MINIMUM_HEAP_CAPACITY (8)
|
||||
#else
|
||||
# define MINIMUM_HEAP_CAPACITY (1 << 25)
|
||||
# define MINIMUM_HEAP_CAPACITY (1 << 10)
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
|
@ -193,7 +193,7 @@ void obj_next_ptr_field_iterator (obj_field_iterator *it);
|
|||
// returns if we are done iterating over fields of the object
|
||||
bool field_is_done_iterator (obj_field_iterator *it);
|
||||
// ptr is pointer to the actual object content, returns pointer to the very beginning of the object (header)
|
||||
void *get_obj_header_ptr (void *ptr, lama_type type);
|
||||
void *get_obj_header_ptr (void *ptr);
|
||||
void *get_object_content_ptr (void *header_ptr);
|
||||
void *get_end_of_obj (void *header_ptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -503,7 +503,7 @@ extern void *Lsubstring (void *subj, int p, int l) {
|
|||
extern struct re_pattern_buffer *Lregexp (char *regexp) {
|
||||
regex_t *b = (regex_t *)malloc(sizeof(regex_t));
|
||||
|
||||
/* printf ("regexp: %s,\test_small_tree_compaction%x\n", regexp, b); */
|
||||
/* printf ("regexp: %s,\t%x\n", regexp, b); */
|
||||
|
||||
memset(b, 0, sizeof(regex_t));
|
||||
|
||||
|
|
@ -1020,7 +1020,7 @@ extern int Btag (void *d, int t, int n) {
|
|||
&& LEN(r->data_header) == UNBOX(n));
|
||||
#else
|
||||
return BOX(TAG(r->data_header) == SEXP_TAG
|
||||
&& GET_SEXP_TAG(TO_SEXP(d)->data_header) == UNBOX(test_small_tree_compaction)
|
||||
&& GET_SEXP_TAG(TO_SEXP(d)->data_header) == UNBOX(t)
|
||||
&& LEN(r->data_header) == UNBOX(n));
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
// this flag makes GC behavior a bit different for testing purposes.
|
||||
//#define DEBUG_VERSION
|
||||
//#define FULL_INVARIANT_CHECKS
|
||||
|
||||
#define STRING_TAG 0x00000001
|
||||
//# define STRING_TAG 0x00000000
|
||||
|
|
@ -48,7 +49,7 @@ typedef struct {
|
|||
// other utility info (i.e., size for array, number of fields for s-expression)
|
||||
int data_header;
|
||||
|
||||
#ifdef DEBUG_VERSION
|
||||
#ifdef FULL_INVARIANT_CHECKS
|
||||
size_t id;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue