|
38 | 38 | #include "py/gc.h" |
39 | 39 |
|
40 | 40 | // Instance of MemoryError exception - needed by mp_malloc_fail |
41 | | -const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, MP_OBJ_NULL, mp_const_empty_tuple}; |
| 41 | +const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, MP_OBJ_NULL, mp_const_empty_tuple}; |
42 | 42 |
|
43 | 43 | // Optionally allocated buffer for storing the first argument of an exception |
44 | 44 | // allocated when the heap is locked. |
@@ -88,7 +88,7 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { |
88 | 88 | // Instance of GeneratorExit exception - needed by generator.close() |
89 | 89 | // This would belong to objgenerator.c, but to keep mp_obj_exception_t |
90 | 90 | // definition module-private so far, have it here. |
91 | | -const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, MP_OBJ_NULL, mp_const_empty_tuple}; |
| 91 | +const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, MP_OBJ_NULL, mp_const_empty_tuple}; |
92 | 92 |
|
93 | 93 | STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { |
94 | 94 | mp_obj_exception_t *o = o_in; |
@@ -126,7 +126,7 @@ mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t |
126 | 126 | o->args = mp_obj_new_tuple(n_args, args); |
127 | 127 | } |
128 | 128 | o->base.type = type_in; |
129 | | - o->traceback = MP_OBJ_NULL; |
| 129 | + o->traceback_data = NULL; |
130 | 130 | return o; |
131 | 131 | } |
132 | 132 |
|
@@ -298,7 +298,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char |
298 | 298 | // Unfortunately, we won't be able to format the string... |
299 | 299 | o = &MP_STATE_VM(mp_emergency_exception_obj); |
300 | 300 | o->base.type = exc_type; |
301 | | - o->traceback = MP_OBJ_NULL; |
| 301 | + o->traceback_data = NULL; |
302 | 302 | o->args = mp_const_empty_tuple; |
303 | 303 |
|
304 | 304 | #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF |
@@ -332,21 +332,17 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char |
332 | 332 | offset += sizeof(void *) - 1; |
333 | 333 | offset &= ~(sizeof(void *) - 1); |
334 | 334 |
|
335 | | - if ((mp_emergency_exception_buf_size - offset) > (sizeof(mp_obj_list_t) + sizeof(mp_obj_t) * 3)) { |
| 335 | + if ((mp_emergency_exception_buf_size - offset) > (sizeof(mp_uint_t) * 3)) { |
336 | 336 | // We have room to store some traceback. |
337 | | - mp_obj_list_t *list = (mp_obj_list_t *)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset); |
338 | | - list->base.type = &mp_type_list; |
339 | | - list->items = (mp_obj_t)&list[1]; |
340 | | - list->alloc = (MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)list->items) / sizeof(list->items[0]); |
341 | | - list->len = 0; |
342 | | - |
343 | | - o->traceback = list; |
| 337 | + o->traceback_data = (mp_uint_t*)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset); |
| 338 | + o->traceback_alloc = (MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]); |
| 339 | + o->traceback_len = 0; |
344 | 340 | } |
345 | 341 | } |
346 | 342 | #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF |
347 | 343 | } else { |
348 | 344 | o->base.type = exc_type; |
349 | | - o->traceback = MP_OBJ_NULL; |
| 345 | + o->traceback_data = NULL; |
350 | 346 | o->args = mp_obj_new_tuple(1, NULL); |
351 | 347 |
|
352 | 348 | if (fmt == NULL) { |
@@ -416,50 +412,47 @@ void mp_obj_exception_clear_traceback(mp_obj_t self_in) { |
416 | 412 | GET_NATIVE_EXCEPTION(self, self_in); |
417 | 413 | // just set the traceback to the null object |
418 | 414 | // we don't want to call any memory management functions here |
419 | | - self->traceback = MP_OBJ_NULL; |
| 415 | + self->traceback_data = NULL; |
420 | 416 | } |
421 | 417 |
|
422 | 418 | void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line, qstr block) { |
423 | 419 | GET_NATIVE_EXCEPTION(self, self_in); |
424 | 420 |
|
425 | | - #if MICROPY_ENABLE_GC |
426 | | - if (gc_is_locked()) { |
427 | | - if (self->traceback == MP_OBJ_NULL) { |
428 | | - // We can't allocate any memory, and no memory has been |
429 | | - // pre-allocated, so there is nothing else we can do. |
| 421 | + // append this traceback info to traceback data |
| 422 | + // if memory allocation fails (eg because gc is locked), just return |
| 423 | + |
| 424 | + if (self->traceback_data == NULL) { |
| 425 | + self->traceback_data = m_new_maybe(mp_uint_t, 3); |
| 426 | + if (self->traceback_data == NULL) { |
430 | 427 | return; |
431 | 428 | } |
432 | | - mp_obj_list_t *list = self->traceback; |
433 | | - if (list->alloc <= (list->len + 3)) { |
434 | | - // There is some preallocated memory, but not enough to store an |
435 | | - // entire record. |
| 429 | + self->traceback_alloc = 3; |
| 430 | + self->traceback_len = 0; |
| 431 | + } else if (self->traceback_len + 3 > self->traceback_alloc) { |
| 432 | + // be conservative with growing traceback data |
| 433 | + mp_uint_t *tb_data = m_renew_maybe(mp_uint_t, self->traceback_data, self->traceback_alloc, self->traceback_alloc + 3); |
| 434 | + if (tb_data == NULL) { |
436 | 435 | return; |
437 | 436 | } |
| 437 | + self->traceback_data = tb_data; |
| 438 | + self->traceback_alloc += 3; |
438 | 439 | } |
439 | | - #endif |
440 | 440 |
|
441 | | - // for traceback, we are just using the list object for convenience, it's not really a list of Python objects |
442 | | - if (self->traceback == MP_OBJ_NULL) { |
443 | | - self->traceback = mp_obj_new_list_maybe(3); |
444 | | - if (self->traceback == MP_OBJ_NULL) { |
445 | | - return; |
446 | | - } |
447 | | - } |
448 | | - mp_obj_list_t *list = self->traceback; |
449 | | - list->items[0] = (mp_obj_t)(mp_uint_t)file; |
450 | | - list->items[1] = (mp_obj_t)(mp_uint_t)line; |
451 | | - list->items[2] = (mp_obj_t)(mp_uint_t)block; |
| 441 | + mp_uint_t *tb_data = &self->traceback_data[self->traceback_len]; |
| 442 | + self->traceback_len += 3; |
| 443 | + tb_data[0] = (mp_uint_t)file; |
| 444 | + tb_data[1] = (mp_uint_t)line; |
| 445 | + tb_data[2] = (mp_uint_t)block; |
452 | 446 | } |
453 | 447 |
|
454 | 448 | void mp_obj_exception_get_traceback(mp_obj_t self_in, mp_uint_t *n, mp_uint_t **values) { |
455 | 449 | GET_NATIVE_EXCEPTION(self, self_in); |
456 | 450 |
|
457 | | - if (self->traceback == MP_OBJ_NULL) { |
| 451 | + if (self->traceback_data == NULL) { |
458 | 452 | *n = 0; |
459 | 453 | *values = NULL; |
460 | 454 | } else { |
461 | | - mp_uint_t n2; |
462 | | - mp_obj_list_get(self->traceback, &n2, (mp_obj_t**)values); |
463 | | - *n = n2; |
| 455 | + *n = self->traceback_len; |
| 456 | + *values = self->traceback_data; |
464 | 457 | } |
465 | 458 | } |
0 commit comments