|
28 | 28 |
|
29 | 29 | // This header file contains definitions to dynamically implement the static
|
30 | 30 | // MicroPython runtime API defined in py/obj.h and py/runtime.h.
|
| 31 | +// |
| 32 | +// All of the symbols made available in this header are overriding those defined |
| 33 | +// in py/obj.h and py/runtime.h. This is done with macros. For macros that |
| 34 | +// would be too complicated (usually more than a single expression), they call a |
| 35 | +// static-inline function for the implementation. This function has the same |
| 36 | +// name as the macro (hence the same name as a public API function) but with |
| 37 | +// "_dyn" appended. For example, the m_malloc() macro calls the m_malloc_dyn() |
| 38 | +// static-inline function. |
31 | 39 |
|
32 | 40 | #include "py/binary.h"
|
33 | 41 | #include "py/nativeglue.h"
|
|
39 | 47 | #error "dynruntime.h included in non-dynamic-module build."
|
40 | 48 | #endif
|
41 | 49 |
|
| 50 | +#if MICROPY_MALLOC_USES_ALLOCATED_SIZE |
| 51 | +#error "MICROPY_MALLOC_USES_ALLOCATED_SIZE must be disable in a dynamic-module build." |
| 52 | +#endif |
| 53 | + |
42 | 54 | #undef MP_ROM_QSTR
|
43 | 55 | #undef MP_OBJ_QSTR_VALUE
|
44 | 56 | #undef MP_OBJ_NEW_QSTR
|
|
52 | 64 | /******************************************************************************/
|
53 | 65 | // Memory allocation
|
54 | 66 |
|
| 67 | +#define m_malloc_fail(num_bytes) (m_malloc_fail_dyn((num_bytes))) |
55 | 68 | #define m_malloc(n) (m_malloc_dyn((n)))
|
56 | 69 | #define m_free(ptr) (m_free_dyn((ptr)))
|
57 | 70 | #define m_realloc(ptr, new_num_bytes) (m_realloc_dyn((ptr), (new_num_bytes)))
|
| 71 | +#define m_realloc_maybe(ptr, new_num_bytes, allow_move) (m_realloc_maybe_dyn((ptr), (new_num_bytes), (allow_move))) |
| 72 | + |
| 73 | +static NORETURN inline void m_malloc_fail_dyn(size_t num_bytes) { |
| 74 | + mp_fun_table.raise_msg( |
| 75 | + mp_fun_table.load_global(MP_QSTR_MemoryError), |
| 76 | + "memory allocation failed"); |
| 77 | +} |
| 78 | + |
| 79 | +static inline void *m_realloc_maybe_dyn(void *ptr, size_t new_num_bytes, bool allow_move) { |
| 80 | + return mp_fun_table.realloc_(ptr, new_num_bytes, allow_move); |
| 81 | +} |
| 82 | + |
| 83 | +static inline void *m_realloc_checked_dyn(void *ptr, size_t new_num_bytes, bool allow_move) { |
| 84 | + ptr = m_realloc_maybe(ptr, new_num_bytes, allow_move); |
| 85 | + if (ptr == NULL && new_num_bytes != 0) { |
| 86 | + m_malloc_fail(new_num_bytes); |
| 87 | + } |
| 88 | + return ptr; |
| 89 | +} |
58 | 90 |
|
59 | 91 | static inline void *m_malloc_dyn(size_t n) {
|
60 |
| - // TODO won't raise on OOM |
61 |
| - return mp_fun_table.realloc_(NULL, n, false); |
| 92 | + return m_realloc_checked_dyn(NULL, n, false); |
62 | 93 | }
|
63 | 94 |
|
64 | 95 | static inline void m_free_dyn(void *ptr) {
|
65 | 96 | mp_fun_table.realloc_(ptr, 0, false);
|
66 | 97 | }
|
67 | 98 |
|
68 | 99 | static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) {
|
69 |
| - // TODO won't raise on OOM |
70 |
| - return mp_fun_table.realloc_(ptr, new_num_bytes, true); |
| 100 | + return m_realloc_checked_dyn(ptr, new_num_bytes, true); |
71 | 101 | }
|
72 | 102 |
|
73 | 103 | /******************************************************************************/
|
|
0 commit comments