From fa3b8951452ca13a807c0b6a090e0385507113db Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 15 Feb 2015 22:24:03 +0300 Subject: [PATCH] objexcept: Optimize traceback allocation for exception. Traceback allocation for exception will now never lead to recursive MemoryError exception - if there's no memory for traceback, it simply won't be created. --- py/objexcept.c | 12 ++++++++---- py/objlist.c | 19 +++++++++++++++++++ py/objlist.h | 2 ++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/py/objexcept.c b/py/objexcept.c index a8b81448ec..858804d0b7 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -436,11 +436,15 @@ void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line, // for traceback, we are just using the list object for convenience, it's not really a list of Python objects if (self->traceback == MP_OBJ_NULL) { - self->traceback = mp_obj_new_list(0, NULL); + self->traceback = mp_obj_new_list_maybe(3); + if (self->traceback == MP_OBJ_NULL) { + return; + } } - mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)file); - mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)line); - mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)block); + mp_obj_list_t *list = self->traceback; + list->items[0] = (mp_obj_t)(mp_uint_t)file; + list->items[1] = (mp_obj_t)(mp_uint_t)line; + list->items[2] = (mp_obj_t)(mp_uint_t)block; } void mp_obj_exception_get_traceback(mp_obj_t self_in, mp_uint_t *n, mp_uint_t **values) { diff --git a/py/objlist.c b/py/objlist.c index 0ff3b1d53d..4768263011 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -477,6 +477,25 @@ mp_obj_t mp_obj_new_list(mp_uint_t n, mp_obj_t *items) { return o; } +// Special method for usage with exceptions +// Doesn't initialize items, assumes they will be initialized by client. +mp_obj_t mp_obj_new_list_maybe(mp_uint_t n) { + mp_obj_list_t *o = m_new_obj_maybe(mp_obj_list_t); + if (!o) { + return o; + } + o->items = m_new_maybe(mp_obj_t, n); + if (!o->items) { + m_del_obj(mp_obj_list_t, o); + return MP_OBJ_NULL; + } + + o->base.type = &mp_type_list; + o->len = o->alloc = n; + + return o; +} + void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) { mp_obj_list_t *self = self_in; *len = self->len; diff --git a/py/objlist.h b/py/objlist.h index 443ede5743..1f3f45212c 100644 --- a/py/objlist.h +++ b/py/objlist.h @@ -35,4 +35,6 @@ typedef struct _mp_obj_list_t { mp_obj_t *items; } mp_obj_list_t; +mp_obj_t mp_obj_new_list_maybe(mp_uint_t n); + #endif // __MICROPY_INCLUDED_PY_OBJLIST_H__