From 4541438e70934fab005fb96d8297615c46be5606 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 26 Aug 2021 19:57:03 +0200 Subject: [PATCH] Berry take into account `bytes()` in gc size --- .../Berry/generate/be_fixed_be_class_bytes.h | 49 +++++++-------- lib/libesp32/Berry/src/be_byteslib.c | 60 +++++++++++-------- lib/libesp32/Berry/src/be_gc.c | 5 +- 3 files changed, 65 insertions(+), 49 deletions(-) diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_bytes.h b/lib/libesp32/Berry/generate/be_fixed_be_class_bytes.h index 58ccee454..76f24a936 100644 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_bytes.h +++ b/lib/libesp32/Berry/generate/be_fixed_be_class_bytes.h @@ -1,36 +1,37 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_bytes_map) { - { be_const_key(dot_p, -1), be_const_var(0) }, - { be_const_key(seti, 6), be_const_func(m_set) }, - { be_const_key(get, 7), be_const_func(m_getu) }, - { be_const_key(size, 10), be_const_func(m_size) }, - { be_const_key(resize, 1), be_const_func(m_resize) }, - { be_const_key(opt_add, 22), be_const_func(m_merge) }, - { be_const_key(getbits, -1), be_const_closure(getbits_closure) }, - { be_const_key(geti, 16), be_const_func(m_geti) }, - { be_const_key(setitem, -1), be_const_func(m_setitem) }, - { be_const_key(add, -1), be_const_func(m_add) }, - { be_const_key(fromb64, -1), be_const_func(m_fromb64) }, - { be_const_key(opt_neq, -1), be_const_func(m_nequal) }, - { be_const_key(set, -1), be_const_func(m_set) }, - { be_const_key(asstring, -1), be_const_func(m_asstring) }, - { be_const_key(copy, 3), be_const_func(m_copy) }, - { be_const_key(opt_eq, 2), be_const_func(m_equal) }, - { be_const_key(tob64, -1), be_const_func(m_tob64) }, - { be_const_key(setbits, 12), be_const_closure(setbits_closure) }, - { be_const_key(_buffer, -1), be_const_func(m_buffer) }, - { be_const_key(fromstring, 0), be_const_func(m_fromstring) }, - { be_const_key(tostring, 9), be_const_func(m_tostring) }, - { be_const_key(item, 8), be_const_func(m_item) }, - { be_const_key(init, 23), be_const_func(m_init) }, + { be_const_key(deinit, -1), be_const_func(m_deinit) }, { be_const_key(opt_connect, -1), be_const_func(m_connect) }, + { be_const_key(item, 3), be_const_func(m_item) }, + { be_const_key(seti, 22), be_const_func(m_set) }, + { be_const_key(asstring, -1), be_const_func(m_asstring) }, + { be_const_key(getbits, -1), be_const_closure(getbits_closure) }, + { be_const_key(copy, -1), be_const_func(m_copy) }, + { be_const_key(get, -1), be_const_func(m_getu) }, + { be_const_key(_buffer, -1), be_const_func(m_buffer) }, + { be_const_key(fromb64, -1), be_const_func(m_fromb64) }, + { be_const_key(add, -1), be_const_func(m_add) }, + { be_const_key(dot_p, -1), be_const_var(0) }, + { be_const_key(size, 0), be_const_func(m_size) }, + { be_const_key(tostring, -1), be_const_func(m_tostring) }, + { be_const_key(opt_add, 10), be_const_func(m_merge) }, + { be_const_key(resize, -1), be_const_func(m_resize) }, + { be_const_key(setitem, -1), be_const_func(m_setitem) }, + { be_const_key(set, -1), be_const_func(m_set) }, + { be_const_key(geti, -1), be_const_func(m_geti) }, + { be_const_key(init, -1), be_const_func(m_init) }, { be_const_key(clear, -1), be_const_func(m_clear) }, + { be_const_key(opt_neq, 23), be_const_func(m_nequal) }, + { be_const_key(tob64, 24), be_const_func(m_tob64) }, + { be_const_key(opt_eq, -1), be_const_func(m_equal) }, + { be_const_key(fromstring, -1), be_const_func(m_fromstring) }, + { be_const_key(setbits, -1), be_const_closure(setbits_closure) }, }; static be_define_const_map( be_class_bytes_map, - 25 + 26 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/lib/libesp32/Berry/src/be_byteslib.c b/lib/libesp32/Berry/src/be_byteslib.c index 5211a0a4c..e63f1932f 100644 --- a/lib/libesp32/Berry/src/be_byteslib.c +++ b/lib/libesp32/Berry/src/be_byteslib.c @@ -419,26 +419,17 @@ static void buf_add_hex(buf_impl* buf, const char *hex, size_t len) /******************************************************************** ** Wrapping into lib ********************************************************************/ -// typedef int (*bntvfunc)(bvm*); /* native function pointer */ -int free_bytes_buf(bvm* vm) -{ - int argc = be_top(vm); - if (argc > 0) { - buf_impl * buf = (buf_impl*) be_tocomptr(vm, 1); - if (buf != NULL) { - be_os_free(buf); - } - } - be_return_nil(vm); -} -buf_impl * bytes_alloc(int32_t size) +buf_impl * bytes_realloc(bvm *vm, buf_impl *oldbuf, int32_t size) { if (size < 4) { size = 4; } if (size > BYTES_MAX_SIZE) { size = BYTES_MAX_SIZE; } - buf_impl * next = (buf_impl*) be_os_malloc(size + BYTES_OVERHEAD); + size_t oldsize = oldbuf ? oldbuf->size + BYTES_OVERHEAD : 0; + buf_impl * next = (buf_impl*) be_realloc(vm, oldbuf, oldsize, size + BYTES_OVERHEAD); /* malloc */ next->size = size; - next->len = 0; + if (!oldbuf) { + next->len = 0; /* allocate a new buffer */ + } return next; } @@ -467,10 +458,10 @@ static int m_init(bvm *vm) } else if (argc > 1 && be_isstring(vm, 2)) { hex_in = be_tostring(vm, 2); if (hex_in) { - size = strlen(hex_in) / 2 + BYTES_HEADROOM; // allocate headroom + size = strlen(hex_in) / 2 + BYTES_HEADROOM; /* allocate headroom */ } } - buf_impl * buf = bytes_alloc(size); + buf_impl * buf = bytes_realloc(vm, NULL, size); /* allocate new buffer */ if (!buf) { be_throw(vm, BE_MALLOC_FAIL); } @@ -478,22 +469,35 @@ static int m_init(bvm *vm) if (hex_in) { buf_add_hex(buf, hex_in, strlen(hex_in)); } - be_newcomobj(vm, buf, &free_bytes_buf); + be_pushcomptr(vm, buf); be_setmember(vm, 1, ".p"); be_return_nil(vm); } +/* deallocate buffer */ +static int m_deinit(bvm *vm) { +{ + be_getmember(vm, 1, ".p"); + buf_impl * buf = be_tocomptr(vm, -1); + be_pop(vm, 1); + if (buf != NULL) { + be_realloc(vm, buf, buf->size + BYTES_OVERHEAD, 0); + } + be_pushcomptr(vm, NULL); /* push NULL pointer instead, just in case */ + be_setmember(vm, 1, ".p"); + be_return_nil(vm); +} +} + /* grow or shrink to the exact value */ /* stack item 1 must contain the instance */ static buf_impl * _bytes_resize(bvm *vm, buf_impl * buf, size_t new_size) { - buf_impl * new_buf = bytes_alloc(new_size); + buf_impl *new_buf = bytes_realloc(vm, buf, new_size); if (!new_buf) { be_throw(vm, BE_MALLOC_FAIL); } - memmove(buf_get_buf(new_buf), buf_get_buf(buf), buf->len); - new_buf->len = buf->len; - /* replace the .p attribute */ - be_newcomobj(vm, new_buf, &free_bytes_buf); + /* replace the .p attribute since address may have changed */ + be_pushcomptr(vm, new_buf); be_setmember(vm, 1, ".p"); be_pop(vm, 1); /* remove comobj from stack */ /* the old buffer will be garbage collected later */ @@ -504,7 +508,13 @@ static buf_impl * _bytes_resize(bvm *vm, buf_impl * buf, size_t new_size) { /* if grow, then add some headroom */ /* stack item 1 must contain the instance */ static buf_impl * bytes_resize(bvm *vm, buf_impl * buf, size_t new_size) { - if (buf->size >= new_size) { return buf; } /* no resize needed */ + /* when resized to smaller, we introduce a new heurstic */ + /* If the buffer is 64 bytes or smaller, don't shrink */ + /* Shrink buffer only if target size is smaller than half the original size */ + if (buf->size >= new_size) { /* enough room, consider if need to shrink */ + if (buf->size <= 64) { return buf; } /* don't shrink if below 64 bytes */ + if (buf->size < new_size * 2) { return buf; } + } return _bytes_resize(vm, buf, new_size + BYTES_HEADROOM); } @@ -1226,6 +1236,7 @@ void be_load_byteslib(bvm *vm) { ".p", NULL }, { "_buffer", m_buffer }, { "init", m_init }, + { "deinit", m_deinit }, { "tostring", m_tostring }, { "asstring", m_asstring }, { "fromstring", m_fromstring }, @@ -1261,6 +1272,7 @@ class be_class_bytes (scope: global, name: bytes) { .p, var _buffer, func(m_buffer) init, func(m_init) + deinit, func(m_deinit) tostring, func(m_tostring) asstring, func(m_asstring) fromstring, func(m_fromstring) diff --git a/lib/libesp32/Berry/src/be_gc.c b/lib/libesp32/Berry/src/be_gc.c index 8e6ac005e..dc5e2d09c 100644 --- a/lib/libesp32/Berry/src/be_gc.c +++ b/lib/libesp32/Berry/src/be_gc.c @@ -461,7 +461,10 @@ static void destruct_object(bvm *vm, bgcobject *obj) type = be_instance_member(vm, ins, str_literal(vm, "deinit"), vm->top); be_incrtop(vm); if (basetype(type) == BE_FUNCTION) { - be_dofunc(vm, vm->top - 1, 1); + var_setinstance(vm->top, ins); /* push instance on stack as arg 1 */ + be_incrtop(vm); + be_dofunc(vm, vm->top - 2, 1); /* warning, there shoudln't be any exception raised here, or the gc stops */ + be_stackpop(vm, 1); } be_stackpop(vm, 1); }