gc wip
This commit is contained in:
parent
16b4410be9
commit
f28b98d43f
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
struct backtrace * backtrace_allocate(struct vm * vm)
|
struct backtrace * backtrace_allocate(struct vm * vm)
|
||||||
{
|
{
|
||||||
|
assert(false); // backtrace must become an objectref
|
||||||
struct backtrace * backtrace = memory_allocate((sizeof (struct backtrace)));
|
struct backtrace * backtrace = memory_allocate((sizeof (struct backtrace)));
|
||||||
backtrace->num_entries = vm->frame_stack.ix;
|
backtrace->num_entries = vm->frame_stack.ix;
|
||||||
int backtrace_entries_size = (sizeof (struct backtrace_entry)) * backtrace->num_entries;
|
int backtrace_entries_size = (sizeof (struct backtrace_entry)) * backtrace->num_entries;
|
||||||
|
@ -151,6 +151,7 @@ static int32_t class_resolver_create_fields_hash_table(int class_hash_table_leng
|
|||||||
class_entry->fields.length = fields_hash_table_length;
|
class_entry->fields.length = fields_hash_table_length;
|
||||||
class_entry->fields.entry = fields_hash_table;
|
class_entry->fields.entry = fields_hash_table;
|
||||||
class_entry->instance_fields_count = instance_index;
|
class_entry->instance_fields_count = instance_index;
|
||||||
|
class_entry->static_fields_count = static_index;
|
||||||
|
|
||||||
return static_index;
|
return static_index;
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ struct class_entry {
|
|||||||
struct class_file * class_file;
|
struct class_file * class_file;
|
||||||
enum initialization_state initialization_state;
|
enum initialization_state initialization_state;
|
||||||
union attribute_entry * attribute_entry;
|
union attribute_entry * attribute_entry;
|
||||||
|
int32_t static_fields_count;
|
||||||
int32_t * static_fields;
|
int32_t * static_fields;
|
||||||
int32_t instance_fields_count;
|
int32_t instance_fields_count;
|
||||||
|
|
||||||
|
119
c/gc.c
Normal file
119
c/gc.c
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
5
c/gc.h
Normal file
5
c/gc.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
void gc_mark(struct vm * vm);
|
@ -72,6 +72,7 @@ void memory_free(void * p)
|
|||||||
assert(buf >= memory);
|
assert(buf >= memory);
|
||||||
uint32_t address_index = buf - memory;
|
uint32_t address_index = buf - memory;
|
||||||
assert(address_index < (sizeof (memory)));
|
assert(address_index < (sizeof (memory)));
|
||||||
|
assert((address_index & (~(block_size - 1))) != address_index);
|
||||||
uint32_t free_list_index = address_index >> block_power;
|
uint32_t free_list_index = address_index >> block_power;
|
||||||
assert((free_list[free_list_index] & START) != 0);
|
assert((free_list[free_list_index] & START) != 0);
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void memory_reset_free_list();
|
void memory_reset_free_list();
|
||||||
void * memory_allocate(uint32_t size);
|
void * memory_allocate(uint32_t size);
|
||||||
void memory_free(void * p);
|
void memory_free(void * p);
|
||||||
|
bool memory_is_allocated(void * p);
|
||||||
|
@ -5,10 +5,22 @@
|
|||||||
|
|
||||||
#include "class_resolver.h"
|
#include "class_resolver.h"
|
||||||
|
|
||||||
struct object_arrayref;
|
enum tag_type {
|
||||||
|
TAG_TYPE_OBJECT = -30741,
|
||||||
|
TAG_TYPE_REF_ARRAY = 23240,
|
||||||
|
TAG_TYPE_PRIM_ARRAY = -5251,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tag {
|
||||||
|
int8_t mark;
|
||||||
|
int8_t _res;
|
||||||
|
int16_t type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert((sizeof (struct tag)) == 4);
|
||||||
|
|
||||||
struct objectref {
|
struct objectref {
|
||||||
int32_t _res;
|
struct tag tag;
|
||||||
struct class_entry * class_entry;
|
struct class_entry * class_entry;
|
||||||
union {
|
union {
|
||||||
struct objectref * oref[0];
|
struct objectref * oref[0];
|
||||||
@ -17,11 +29,12 @@ struct objectref {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert((sizeof (struct objectref)) == 8);
|
static_assert((sizeof (struct objectref)) == 12);
|
||||||
|
|
||||||
struct arrayref {
|
struct arrayref {
|
||||||
int32_t length; // length position must match primitive_arrayref
|
struct tag tag;
|
||||||
struct class_entry * class_entry;
|
struct class_entry * class_entry;
|
||||||
|
int32_t length;
|
||||||
union {
|
union {
|
||||||
// object array:
|
// object array:
|
||||||
struct objectref * oref[0];
|
struct objectref * oref[0];
|
||||||
@ -34,7 +47,7 @@ struct arrayref {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert((sizeof (struct arrayref)) == 8);
|
static_assert((sizeof (struct arrayref)) == 12);
|
||||||
|
|
||||||
enum ARRAY_TYPE {
|
enum ARRAY_TYPE {
|
||||||
T_BOOLEAN = 4, // 1 byte
|
T_BOOLEAN = 4, // 1 byte
|
||||||
|
Loading…
x
Reference in New Issue
Block a user