Skip to content
Snippets Groups Projects
Commit 4f7e9f5c authored by mux's avatar mux
Browse files

Implement del

parent 094d4500
No related branches found
No related tags found
No related merge requests found
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "mpconfig.h"
#include "gc.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#if MICROPY_ENABLE_GC
#if 0 // print debugging info
......@@ -20,7 +25,9 @@ typedef unsigned char byte;
#define STACK_SIZE (64) // tunable; minimum is 1
STATIC byte *gc_alloc_table_start;
STATIC byte *gc_mpobj_table_start;
STATIC machine_uint_t gc_alloc_table_byte_len;
STATIC machine_uint_t gc_mpobj_table_byte_len;
STATIC machine_uint_t *gc_pool_start;
STATIC machine_uint_t *gc_pool_end;
......@@ -58,6 +65,10 @@ STATIC machine_uint_t *gc_sp;
#define ATB_HEAD_TO_MARK(block) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0)
#define ATB_MARK_TO_HEAD(block) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0)
#define ATB_SET_MPOBJ(block) do { gc_mpobj_table_start[(block) / 8] |= (1<<(block%8)); } while (0)
#define ATB_CLR_MPOBJ(block) do { gc_mpobj_table_start[(block) / 8] &= (~(1<<(block%8))); } while (0)
#define ATB_IS_MPOBJ(block) ((gc_mpobj_table_start[(block) / 8]>>(block%8))&0x01)
#define BLOCK_FROM_PTR(ptr) (((ptr) - (machine_uint_t)gc_pool_start) / BYTES_PER_BLOCK)
#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (machine_uint_t)gc_pool_start))
#define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB)
......@@ -72,7 +83,11 @@ void gc_init(void *start, void *end) {
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;
machine_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BITS_PER_BYTE / 2;
gc_mpobj_table_byte_len = (gc_alloc_table_byte_len * BITS_PER_BYTE / 2)/8;
gc_mpobj_table_start = 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) -(gc_mpobj_table_byte_len / BYTES_PER_BLOCK);
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;
......@@ -80,6 +95,9 @@ void gc_init(void *start, void *end) {
// clear ATBs
memset(gc_alloc_table_start, 0, gc_alloc_table_byte_len);
// clear MPOBJ flags
memset(gc_mpobj_table_start, 0, gc_mpobj_table_byte_len);
// allocate first block because gc_pool_start points there and it will never
// be freed, so allocating 1 block with null pointers will minimise memory loss
ATB_FREE_TO_HEAD(0);
......@@ -156,6 +174,14 @@ STATIC void gc_sweep(void) {
for (machine_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
switch (ATB_GET_KIND(block)) {
case AT_HEAD:
if (ATB_IS_MPOBJ(block)) {
ATB_CLR_MPOBJ(block); // clear mpobj flag
mp_obj_t *self = (mp_obj_t*)PTR_FROM_BLOCK(block);
mp_obj_type_t *type= mp_obj_get_type(self);
if (type->del != NULL) {
type->del(self);
}
}
free_tail = 1;
// fall through to free the head
......@@ -236,7 +262,7 @@ void gc_info(gc_info_t *info) {
info->free *= BYTES_PER_BLOCK;
}
void *gc_alloc(machine_uint_t n_bytes) {
void *_gc_alloc(machine_uint_t n_bytes, bool is_mpobj) {
machine_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks);
......@@ -279,6 +305,10 @@ found:
// mark first block as used head
ATB_FREE_TO_HEAD(start_block);
if (is_mpobj) {
ATB_SET_MPOBJ(start_block);
}
// mark rest of blocks as used tail
// TODO for a run of many blocks can make this more efficient
for (machine_uint_t bl = start_block + 1; bl <= end_block; bl++) {
......@@ -289,6 +319,14 @@ found:
return (void*)(gc_pool_start + start_block * WORDS_PER_BLOCK);
}
void *gc_alloc(machine_uint_t n_bytes) {
return _gc_alloc(n_bytes, false);
}
void *gc_alloc_mp_obj(machine_uint_t n_bytes) {
return _gc_alloc(n_bytes, true);
}
// force the freeing of a piece of memory
void gc_free(void *ptr_in) {
machine_uint_t ptr = (machine_uint_t)ptr_in;
......
......@@ -4,6 +4,7 @@ void gc_collect_root(void **ptrs, machine_uint_t len);
void gc_collect_end(void);
void gc_collect(void);
void *gc_alloc(machine_uint_t n_bytes);
void *gc_alloc_mp_obj(machine_uint_t n_bytes);
void gc_free(void *ptr);
machine_uint_t gc_nbytes(void *ptr);
void *gc_realloc(void *ptr, machine_uint_t n_bytes);
......
......@@ -31,6 +31,7 @@ STATIC int peak_bytes_allocated = 0;
#undef free
#undef realloc
#define malloc gc_alloc
#define malloc_mp_obj gc_alloc_mp_obj
#define free gc_free
#define realloc gc_realloc
#endif // MICROPY_ENABLE_GC
......@@ -53,6 +54,24 @@ void *m_malloc(int num_bytes) {
return ptr;
}
void *m_malloc_mp_obj(int num_bytes) {
if (num_bytes == 0) {
return NULL;
}
void *ptr = malloc_mp_obj(num_bytes);
if (ptr == NULL) {
printf("could not allocate memory, allocating %d bytes\n", num_bytes);
return NULL;
}
#if MICROPY_MEM_STATS
total_bytes_allocated += num_bytes;
current_bytes_allocated += num_bytes;
UPDATE_PEAK();
#endif
DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
return ptr;
}
void *m_malloc0(int num_bytes) {
void *ptr = m_malloc(num_bytes);
if (ptr != NULL) {
......
......@@ -27,12 +27,14 @@ typedef unsigned int uint;
#define m_new0(type, num) ((type*)(m_malloc0(sizeof(type) * (num))))
#define m_new_obj(type) (m_new(type, 1))
#define m_new_obj_var(obj_type, var_type, var_num) ((obj_type*)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num)))
#define m_new_mp_obj(type)((type*)(m_malloc_mp_obj(sizeof(type))))
#define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num))))
#define m_del(type, ptr, num) m_free(ptr, sizeof(type) * (num))
#define m_del_obj(type, ptr) (m_del(type, ptr, 1))
#define m_del_var(obj_type, var_type, var_num, ptr) (m_free(ptr, sizeof(obj_type) + sizeof(var_type) * (var_num)))
void *m_malloc(int num_bytes);
void *m_malloc_mp_obj(int num_bytes);
void *m_malloc0(int num_bytes);
void *m_realloc(void *ptr, int old_num_bytes, int new_num_bytes);
void m_free(void *ptr, int num_bytes);
......
......@@ -154,6 +154,7 @@ typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
typedef void (*mp_load_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); // for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
typedef bool (*mp_store_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t value); // return true if store succeeded
typedef bool (*mp_store_item_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); // return true if store succeeded
typedef void (*mp_del_fun_t)(mp_obj_t self_in);
typedef struct _mp_method_t {
qstr name;
......@@ -236,6 +237,7 @@ struct _mp_obj_type_t {
unpack seq list tuple
*/
mp_del_fun_t del;
};
typedef struct _mp_obj_type_t mp_obj_type_t;
......
......@@ -13,6 +13,12 @@ typedef struct _pyb_file_obj_t {
FIL fp;
} pyb_file_obj_t;
void file_obj_del(mp_obj_t self_in) {
pyb_file_obj_t *self = self_in;
f_close(&self->fp);
printf("<file del called>\n");
}
void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
printf("<file %p>", self_in);
}
......@@ -64,13 +70,14 @@ static const mp_obj_type_t file_obj_type = {
{ &mp_type_type },
.name = MP_QSTR_File,
.print = file_obj_print,
.del = file_obj_del,
.locals_dict = (mp_obj_t)&file_locals_dict,
};
mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
const char *filename = mp_obj_str_get_str(o_filename);
const char *mode = mp_obj_str_get_str(o_mode);
pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t);
pyb_file_obj_t *self = m_new_mp_obj(pyb_file_obj_t);
self->base.type = &file_obj_type;
if (mode[0] == 'r') {
// open for reading
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment