Skip to content

Implement del #425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 5, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions py/gc.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include "mpconfig.h"
#include "gc.h"

#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"

#if MICROPY_ENABLE_GC

#if 0 // print debugging info
Expand All @@ -20,7 +26,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;

Expand Down Expand Up @@ -58,6 +66,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)
Expand All @@ -72,14 +84,21 @@ 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;

// 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);
Expand Down Expand Up @@ -156,6 +175,16 @@ 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)) {
mp_obj_t dest[2];
mp_load_method((mp_obj_t*)PTR_FROM_BLOCK(block), MP_QSTR___del__, dest);
// load_method returned a method
if (dest[1] != MP_OBJ_NULL) {
mp_call_method_n_kw(0, 0, dest);
}
// clear mpobj flag
ATB_CLR_MPOBJ(block);
}
free_tail = 1;
// fall through to free the head

Expand Down Expand Up @@ -236,7 +265,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);

Expand Down Expand Up @@ -285,10 +314,23 @@ void *gc_alloc(machine_uint_t n_bytes) {
ATB_FREE_TO_TAIL(bl);
}

if (is_mpobj) {
// set mp_obj flag only if it has del
ATB_SET_MPOBJ(start_block);
}

// return pointer to first block
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;
Expand Down
1 change: 1 addition & 0 deletions py/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions py/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions py/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions py/qstrdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Q(__sub__)
Q(__repr__)
Q(__str__)
Q(__getattr__)
Q(__del__)

Q(micropython)
Q(byte_code)
Expand Down
3 changes: 2 additions & 1 deletion stm/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ STATIC const mp_map_elem_t file_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&file_obj_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&file_obj_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&file_obj_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&file_obj_close_obj },
};

STATIC MP_DEFINE_CONST_DICT(file_locals_dict, file_locals_dict_table);
Expand All @@ -70,7 +71,7 @@ static const mp_obj_type_t file_obj_type = {
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
Expand Down