Skip to content

Commit fa3b895

Browse files
committed
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.
1 parent 29c4f92 commit fa3b895

3 files changed

Lines changed: 29 additions & 4 deletions

File tree

py/objexcept.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,15 @@ void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line,
436436

437437
// for traceback, we are just using the list object for convenience, it's not really a list of Python objects
438438
if (self->traceback == MP_OBJ_NULL) {
439-
self->traceback = mp_obj_new_list(0, NULL);
439+
self->traceback = mp_obj_new_list_maybe(3);
440+
if (self->traceback == MP_OBJ_NULL) {
441+
return;
442+
}
440443
}
441-
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)file);
442-
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)line);
443-
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)block);
444+
mp_obj_list_t *list = self->traceback;
445+
list->items[0] = (mp_obj_t)(mp_uint_t)file;
446+
list->items[1] = (mp_obj_t)(mp_uint_t)line;
447+
list->items[2] = (mp_obj_t)(mp_uint_t)block;
444448
}
445449

446450
void mp_obj_exception_get_traceback(mp_obj_t self_in, mp_uint_t *n, mp_uint_t **values) {

py/objlist.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,25 @@ mp_obj_t mp_obj_new_list(mp_uint_t n, mp_obj_t *items) {
477477
return o;
478478
}
479479

480+
// Special method for usage with exceptions
481+
// Doesn't initialize items, assumes they will be initialized by client.
482+
mp_obj_t mp_obj_new_list_maybe(mp_uint_t n) {
483+
mp_obj_list_t *o = m_new_obj_maybe(mp_obj_list_t);
484+
if (!o) {
485+
return o;
486+
}
487+
o->items = m_new_maybe(mp_obj_t, n);
488+
if (!o->items) {
489+
m_del_obj(mp_obj_list_t, o);
490+
return MP_OBJ_NULL;
491+
}
492+
493+
o->base.type = &mp_type_list;
494+
o->len = o->alloc = n;
495+
496+
return o;
497+
}
498+
480499
void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
481500
mp_obj_list_t *self = self_in;
482501
*len = self->len;

py/objlist.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,6 @@ typedef struct _mp_obj_list_t {
3535
mp_obj_t *items;
3636
} mp_obj_list_t;
3737

38+
mp_obj_t mp_obj_new_list_maybe(mp_uint_t n);
39+
3840
#endif // __MICROPY_INCLUDED_PY_OBJLIST_H__

0 commit comments

Comments
 (0)