Skip to content

Commit

Permalink
cleanup, solidifying gc
Browse files Browse the repository at this point in the history
  • Loading branch information
reginaldford committed Oct 23, 2024
1 parent c15a9e1 commit b667c11
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 99 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ CC_DEBUG := clang
CC_PROF := clang
CC_UNIFIED := zig cc
# CC_UNIFIED := zig cc -target x86_64-windows-gnu #doesnt work
CFLAGS := -O3
CFLAGS := -O1
CFLAGS_DEBUG := -g
CFLAGS_PROF := -fprofile-instr-generate -fcoverage-mapping
BUILD_DIR := build
Expand Down
16 changes: 7 additions & 9 deletions sms_src/examples/clock.sms
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/local/bin/sms -qm48k
# Simply puts the time every second
# Simply let a=s the time every second
{
# Represents a number from 0 to 99
# with 2 characters.
Expand All @@ -16,18 +16,16 @@
while(true){
d = date();
# Clear the screen
osExec("clear");
# Convert military time to 12-hr
put(two_digits(
let a=(two_digits(
if(d[2]>12)
d[2]-12
else
d[2]));
put(":");
put(two_digits(d[1]));
put(":");
put(two_digits(d[0]));
putLn(" " str+ am_pm_str(d[2]));
sleep(100);
let a=(":");
let a=(two_digits(d[1]));
let a=(":");
let a=(two_digits(d[0]));
let a=(" " str+ am_pm_str(d[2]));
};
};
124 changes: 63 additions & 61 deletions src/main/memory/sm_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,22 @@ sm_object *sm_deep_copy(sm_object *obj) {
// Copy the object to the new heap
// Leave an sm_pointer in the old space
sm_object *sm_move_to_new_heap(sm_heap *dest, sm_object *obj) {
sm_object *new_obj = sm_realloc_at(dest, obj, sm_sizeof(obj));
// Overwrite the old object. sm_pointer is NOT larger
sm_new_pointer(dest, obj, new_obj);
uint32_t sizeOfObj = sm_sizeof(obj);
sm_object *new_obj = sm_realloc_at(dest, obj, sizeOfObj);
// Overwrite the old object. sm_pointer objects
intptr_t endPoint = (intptr_t)obj + sizeOfObj;
while ((intptr_t)obj < endPoint) {
sm_new_pointer(dest, obj, new_obj);
obj = (sm_object *)((intptr_t)obj + sizeof(sm_pointer));
}
return new_obj;
}

// If obj is an sm_pointer, the object was already moved to the new heap
// Else, copy the object to the new heap and leave an sm_pointer
// Expects sm_heap_scan to be used on this to have populated map
// Else if the object is in the source heap, copy the object to the desth heap and leave an
// sm_pointer Expects sm_heap_scan to be used on this to have populated map
sm_object *sm_meet_object(sm_heap *source, sm_heap *dest, sm_object *obj) {
// Only gc objects from sms_other_heap, which used to be sms_heap
// Only gc objects from source
if (sm_heap_has_object(source, obj)) {
uint32_t obj_type = obj->my_type;
if (obj_type == SM_POINTER_TYPE)
Expand Down Expand Up @@ -150,6 +155,11 @@ void sm_inflate_heap(sm_heap *from, sm_heap *to) {
sm_stack_obj *stack = (sm_stack_obj *)current_obj;
for (uint32_t i = 0; i < sm_stack_obj_size(stack); i++)
((sm_object **)&stack[1])[i] = sm_meet_object(from, to, ((sm_object **)&stack[1])[i]);

// Rely on map to update stack's top ptr
// Trace the map leftward from the curent stack->top for the next set bit


break;
}
case SM_ARRAY_TYPE: {
Expand All @@ -165,60 +175,52 @@ void sm_inflate_heap(sm_heap *from, sm_heap *to) {

// Copying GC
void sm_garbage_collect() {
if (sms_heap->used != 0) {
// Fill in the heap map
sm_heap_scan(sms_heap);
// Build "to" heap if necessary, same size as current
if (sms_other_heap == NULL)
sms_other_heap = sm_new_heap(sms_heap->capacity, true);
// Clear other heap for when we recycle a heap
sm_heap_clear(sms_other_heap);
// Try to shake off objects from callstack with unregistered spacer
if (evaluating)
sm_new_space_at(sms_other_heap, (sm_gc_count(0) % 16) * 8);
// Fix c callstack ptrs if evaluating
if (evaluating) {
memory_marker2 = __builtin_frame_address(0) ;
void **lowerPtr = memory_marker1 < memory_marker2 ? memory_marker1 : memory_marker2;
void **higherPtr = memory_marker1 < memory_marker2 ? memory_marker2 : memory_marker1;
for (void **ptr = lowerPtr; ptr < higherPtr; ptr++)
if (sm_heap_has_object(sms_heap, *ptr))
*ptr = (void *)sm_meet_object(sms_heap, sms_other_heap, (sm_object *)*ptr);
}
// Copy root (global context)
*sm_global_lex_stack(NULL)->top =
sm_meet_object(sms_heap, sms_other_heap, (sm_object *)*sm_global_lex_stack(NULL)->top);
// Treat parser output as root or set parser output to false
if (evaluating)
sm_global_parser_output(
sm_meet_object(sms_heap, sms_other_heap, sm_global_parser_output(NULL)));
else
sm_global_parser_output((sm_object *)sms_false);
// Fix c callstack ptrs if evaluating
if (evaluating) {
memory_marker2 = __builtin_frame_address(0);
// Fill in the heap bitmap
void **lowerPtr = memory_marker1 < memory_marker2 ? memory_marker1 : memory_marker2;
void **higherPtr = memory_marker1 < memory_marker2 ? memory_marker2 : memory_marker1;
// Scan callstack for valid object ptrs
for (void **ptr = lowerPtr; ptr < higherPtr; ptr++)
if (sm_heap_has_object(sms_heap, *ptr))
*ptr = (void *)sm_meet_object(sms_heap, sms_other_heap, (sm_object *)*ptr);
}
// Inflate
sm_inflate_heap(sms_heap, sms_other_heap);
// For tracking purposes
sm_gc_count(1);
// swap global heap ptrs
sm_swap_heaps(&sms_heap, &sms_other_heap);
// Report memory stat
if (sm_global_environment(NULL) && sm_global_environment(NULL)->quiet_mode == false) {
char used_str[16];
char capacity_str[16];
sm_sprint_fancy_bytelength(used_str, (uint64_t)sms_heap->used);
sm_sprint_fancy_bytelength(capacity_str, (uint64_t)sms_heap->capacity);
printf("\n%s(%s / %s)%s\n", sm_terminal_fg_color(SM_TERM_B_BLACK), used_str, capacity_str,
sm_terminal_reset());
}
if (!sms_heap->used)
return;
// Fill in the heap map
if (!sm_heap_scan(sms_heap)) {
fprintf(stderr, "Heap scan failed. Exiting with code 1\n");
exit(1);
}
// Build "to" heap if necessary, same size as current
if (!sms_other_heap)
sms_other_heap = sm_new_heap(sms_heap->capacity, true);
// Clear other heap for when we recycle a heap
sm_heap_clear(sms_other_heap);
// Try to shake off objects from callstack with unregistered spacer
if (evaluating)
sm_new_space_at(sms_other_heap, ((sms_heap > sms_other_heap) + (sm_gc_count(0) & 7)) << 3);
// Fix c callstack ptrs if evaluating
if (evaluating) {
memory_marker2 = __builtin_frame_address(0);
void **lowerPtr = memory_marker1 < memory_marker2 ? memory_marker1 : memory_marker2;
void **higherPtr = memory_marker1 < memory_marker2 ? memory_marker2 : memory_marker1;
for (void **ptr = lowerPtr; ptr < higherPtr; ptr++)
if (sm_heap_has_object(sms_heap, *ptr) && sm_sizeof((sm_object *)*ptr))
*ptr = (void *)sm_meet_object(sms_heap, sms_other_heap, (sm_object *)*ptr);
}
// Copy root (global context)
*sm_global_lex_stack(NULL)->top =
sm_meet_object(sms_heap, sms_other_heap, (sm_object *)*sm_global_lex_stack(NULL)->top);
// Treat parser output as root or set parser output to false
if (evaluating)
sm_global_parser_output(
sm_meet_object(sms_heap, sms_other_heap, sm_global_parser_output(NULL)));
else
sm_global_parser_output((sm_object *)sms_false);
// Inflate
sm_inflate_heap(sms_heap, sms_other_heap);
// For tracking purposes
sm_gc_count(1);
// swap global heap ptrs
sm_swap_heaps(&sms_heap, &sms_other_heap);
// Report memory stat
if (sm_global_environment(NULL) && sm_global_environment(NULL)->quiet_mode == false) {
char used_str[16];
char capacity_str[16];
sm_sprint_fancy_bytelength(used_str, (uint64_t)sms_heap->used);
sm_sprint_fancy_bytelength(capacity_str, (uint64_t)sms_heap->capacity);
printf("\n%s(%s / %s)%s\n", sm_terminal_fg_color(SM_TERM_B_BLACK), used_str, capacity_str,
sm_terminal_reset());
}
}
51 changes: 25 additions & 26 deletions src/main/memory/sm_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ void *sm_malloc_at(sm_heap *h, uint32_t size) {
// Get the pointer to the newly allocated space
void *allocated_space = (void *)(((char *)h->storage) + bytes_used);
// Give this chunk a valid sm_space header so that it survives gc
sm_space *space = (sm_space *)allocated_space;
space->my_type = SM_SPACE_TYPE;
space->size = sm_round_size64(size) - sizeof(sm_space);
memset(allocated_space, 0, size);
return allocated_space; // Return the pointer to the allocated space
}

Expand All @@ -86,27 +84,29 @@ void sm_heap_print_map(sm_heap *h) {

// Return whether this pointer aims at the beginning of a registered heap object
bool sm_heap_has_object(sm_heap *heap, void *guess) {
// First check if it's in bounds
// First check if it's aligned and in bounds
if (((intptr_t)guess & 7) || !sm_is_within_heap(guess, heap))
return false;
// Calculate the position in the bitmap
uint32_t map_pos =
((intptr_t *)guess - (intptr_t *)heap->storage) / 8; // Offset in the heap divided by 8 bytes
uint32_t byte_pos = map_pos / 8; // Find the byte in the bitmap
uint32_t bit_pos = map_pos % 8; // Find the specific bit in the byte
((intptr_t *)guess - (intptr_t *)heap->storage) >> 3; // Offset in the heap divided by 8 bytes
uint32_t byte_pos = map_pos >> 3; // Find the byte in the bitmap
uint32_t bit_pos = map_pos & 7; // Find the specific bit in the byte
return heap->map[byte_pos] & (1 << bit_pos);
}

// Designed to be fast
void sm_heap_register_object(sm_heap *heap, void *obj) {
if (heap->map) {
// Calculate the position in the bitmap
uint32_t map_pos =
((intptr_t *)obj - (intptr_t *)heap->storage) / 8; // Offset in the heap divided by 8 bytes
uint32_t byte_pos = map_pos / 8; // Find the byte in the bitmap
uint32_t bit_pos = map_pos % 8; // Find the specific bit in the byte
heap->map[byte_pos] |= (1 << bit_pos);
if (((intptr_t)obj) & 7) {
fprintf(stderr, "Misaligned object registration. File: %s Line: %u\n", __FILE__, __LINE__);
exit(1);
}
// Calculate the position in the bitmap
uint32_t map_pos =
((intptr_t *)obj - (intptr_t *)heap->storage) >> 3; // Offset in the heap divided by 8 bytes
uint32_t byte_pos = map_pos >> 3; // Find the byte in the bitmap
uint32_t bit_pos = map_pos & 7; // Find the specific bit in the byte
heap->map[byte_pos] |= (1 << bit_pos);
}

// Reallocate memory space for resizing or recreating objects
Expand All @@ -133,7 +133,7 @@ void sm_heap_clear(struct sm_heap *h) {

// Is the ptr within this heap?
bool sm_is_within_heap(void *ptr, sm_heap *heap) {
return (ptr >= (void *)heap->storage) && (ptr < (void *)((char *)heap->storage) + heap->used);
return (ptr >= (void *)heap->storage) && (ptr < (void *)(heap->storage) + heap->used);
}

// For advanced debugging, run this at any point and examine the heap snapshot as a file
Expand All @@ -157,16 +157,12 @@ void sm_dump_and_count() {
snprintf(fname, 12 + index_len, "current_%i.mem", index);
sm_mem_dump(sms_heap, fname);
snprintf(fname, 10 + index_len, "other_%i.mem", index);
sm_mem_dump(sms_heap, fname);
sm_mem_dump(sms_other_heap, fname);
index++;
}

// Free the heaps, preparing for closing or restarting
void sm_mem_cleanup() {
sm_heap_set_free(sms_all_heaps);
if (sm_global_lex_stack(NULL))
free(sm_global_lex_stack(NULL));
}
void sm_mem_cleanup() { sm_heap_set_free(sms_all_heaps); }

// Print every object in current heap
void sm_sprint_dump() {
Expand Down Expand Up @@ -199,13 +195,16 @@ bool sm_heap_scan(sm_heap *h) {
sm_object *obj = (sm_object *)((intptr_t)h->storage);
sm_object *prev_obj = NULL; // Initialize prev_obj to track the previous object
while ((char *)obj < h->storage + h->used) {
// Check for valid object size
// Register in heap map if it has one
if (sm_sizeof(obj))
sm_heap_register_object(sms_heap, obj);
// Register in heap map if it has valid object size
uint32_t sizeOfObj = sm_sizeof(obj);
if (!sizeOfObj || sizeOfObj & 7) {
fprintf(stderr, "! Corrupt object. File: %s , line: %u\n", __FILE__, __LINE__);
return false;
}
sm_heap_register_object(sms_heap, obj);
// Move to the next object
prev_obj = obj; // Update prev_obj to the current object
obj = (sm_object *)((char *)obj + MAX(sm_sizeof(obj), sizeof(size_t)));
obj = (sm_object *)((char *)obj + (sizeOfObj));
}
return true;
}
6 changes: 5 additions & 1 deletion src/main/object/sm_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ uint32_t sm_object_sprint(sm_object *obj1, char *buffer, bool fake) {
// Return the size of the object in bytes

uint32_t sm_sizeof(sm_object *obj1) {
if ((intptr_t)obj1 & 7) {
fprintf(stderr, "! misaligned object File: %s Line: %u\n", __FILE__, __LINE__);
exit(1);
}
switch (obj1->my_type) {
case SM_F64_TYPE:
return sizeof(sm_f64);
Expand Down Expand Up @@ -103,7 +107,7 @@ uint32_t sm_sizeof(sm_object *obj1) {
case SM_RETURN_TYPE:
return sizeof(sm_return);
case SM_STACK_OBJ_TYPE:
return sizeof(sm_stack) + sizeof(void *) * sm_stack_obj_size((sm_stack_obj *)obj1);
return sizeof(sm_stack_obj) + sizeof(void *) * ((sm_stack_obj *)obj1)->capacity;
case SM_ARRAY_TYPE:
return sizeof(sm_array);
case SM_UI8_TYPE:
Expand Down
2 changes: 1 addition & 1 deletion src/main/object/sm_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ sm_string *sm_new_string_manual_at(struct sm_heap *heap, uint32_t size) {
}

// Return a new empty string (does not nullify contents)
sm_string *sm_new_string_manual(uint32_t size) { return sm_new_string_manual_at(sms_heap,size); }
sm_string *sm_new_string_manual(uint32_t size) { return sm_new_string_manual_at(sms_heap, size); }

// Return a new string: str1+str2
sm_string *sm_string_add(sm_string *str1, sm_string *str2) {
Expand Down

0 comments on commit b667c11

Please sign in to comment.