Select Git revision
Forked from
flow3r / flow3r firmware
Source project has a limited visibility.
gc.c 11.89 KiB
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "mpyconfig.h"
#include "gc.h"
// a machine word is big enough to hold a pointer
/*
#define BYTES_PER_WORD (8)
typedef unsigned long machine_uint_t;
*/
typedef unsigned char byte;
#define BITS_PER_BYTE (8)
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
#define WORDS_PER_BLOCK (4)
#define BYTES_PER_BLOCK (WORDS_PER_BLOCK * BYTES_PER_WORD)
#define STACK_SIZE (64) // tunable; minimum is 1
static byte *gc_alloc_table_start;
static byte *gc_alloc_table_end;
static machine_uint_t gc_alloc_table_byte_len;
static machine_uint_t *gc_pool_start;
static machine_uint_t *gc_pool_end;
static int gc_stack_overflow;
static machine_uint_t gc_stack[STACK_SIZE];
static machine_uint_t *gc_sp;
// TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool
void gc_init(void *start, void *end) {
// align end pointer on block boundary
end = (void*)((machine_uint_t)end & (~(BYTES_PER_BLOCK - 1)));
// calculate parameters for GC
machine_uint_t total_word_len = (machine_uint_t*)end - (machine_uint_t*)start;
gc_alloc_table_byte_len = total_word_len * BYTES_PER_WORD / (1 + BITS_PER_BYTE / 2 * BYTES_PER_BLOCK);
gc_alloc_table_start = (byte*)start;
gc_alloc_table_end = gc_alloc_table_start + gc_alloc_table_byte_len;
machine_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BITS_PER_BYTE / 2;
machine_uint_t gc_pool_word_len = gc_pool_block_len * WORDS_PER_BLOCK;
gc_pool_start = (machine_uint_t*)end - gc_pool_word_len;
gc_pool_end = end;
// clear ATBs
memset(gc_alloc_table_start, 0, gc_alloc_table_byte_len);
/*
printf("GC layout:\n");
printf(" alloc table at %p, length %u bytes\n", gc_alloc_table_start, gc_alloc_table_byte_len);
printf(" pool at %p, length %u blocks = %u words = %u bytes\n", gc_pool_start, gc_pool_block_len, gc_pool_word_len, gc_pool_word_len * BYTES_PER_WORD);
*/
}
// ATB = allocation table byte
// 0b00 = FREE -- free block
// 0b01 = HEAD -- head of a chain of blocks
// 0b10 = TAIL -- in the tail of a chain of blocks
// 0b11 = MARK -- marked head block
#define AT_FREE (0)
#define AT_HEAD (1)
#define AT_TAIL (2)
#define AT_MARK (3)
#define BLOCKS_PER_ATB (4)
#define ATB_MASK_0 (0x03)
#define ATB_MASK_1 (0x0c)