jvm/c/gc.c
2025-01-09 16:40:50 -06:00

120 lines
2.7 KiB
C

#include "frame.h"
#include "memory_allocator.h"
static void walk_address(void * address);
static void walk_object(struct objectref * objectref)
{
if (arrayref->tag->mark != 0)
return;
objectref->tag->mark = 1;
for (int i = 0; i < objectref->class_entry->instance_fields_count; i++) {
void * address = objectref->aref[i];
walk_address(address);
}
}
static void walk_ref_array(struct arrayref * arrayref)
{
if (arrayref->tag->mark != 0)
return;
arrayref->tag->mark = 1;
if (arrayref->class_entry == nullptr) {
// this is an array of arrayrefs
for (int i = 0; i < arrayref->length; i++) {
if (arrayref->aref[i] != nullptr) {
walk_ref_array(arrayref->aref[i]);
}
}
} else {
// this is an array of objectrefs
for (int i = 0; i < arrayref->length; i++) {
if (arrayref->oref[i] != nullptr) {
walk_object(arrayref->oref[i]);
}
}
}
}
static void walk_address(void * address)
{
if (address == nullptr)
return;
if (!memory_is_allocated(address))
return;
struct tag * tag = (struct tag *)address;
if (tag->type == TAG_TYPE_OBJECT) {
walk_object((struct objectref *)address);
}
if (tag->type == TAG_TYPE_REF_ARRAY) {
walk_ref_array((struct arrayref *)address);
}
}
static void walk_frame(struct frame * frame)
{
int num_local_variables = frame->code_attribute->max_locals;
int num_stack_variables = frame->operand_stack_ix;
for (int i = 0; i < num_local_variables; i++) {
void * address = frame->local_variable[i];
walk_address(address);
}
for (int i = 0; i < num_stack_variables; i++) {
void * address = frame->operand_stack[i];
walk_address(address);
}
}
static void walk_static_fields(struct class_entry * class_entry)
{
for (int i = 0; i < class_entry->static_fields_count; i++) {
void * address = class_entry->static_fields[i];
walk_address(address);
}
}
static void walk_class_hash_table_entry(struct hash_table_entry * entry)
{
if (entry->key == nullptr)
return;
struct class_entry * class_entry = (struct class_entry *)e->value;
assert(class_entry != nullptr);
walk_static_fiends(class_entry);
if (entry->next != nullptr)
walk_class_hash_table_entry(entry->next);
}
static void walk_class_hash_table(int length, struct hash_table_entry * entry)
{
for (int i = 0; i < length; i++)
walk_class_hash_table_entry(&entry[i]);
}
static void walk_vm(struct vm * vm)
{
walk_class_hash_table(vm->class_hash_table.length,
vm->class_hash_table.entry);
for (int i = 0; i < vm->frame_stack->ix; i++) {
walk_frame(&vm->frame_stack->frame[i]);
}
}
void gc_mark(struct vm * vm)
{
walk_vm(vm);
}
void gc_sweep()
{
}