diff --git a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk index 3a0eeb3f2130e..3dbef7c576a13 100644 --- a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk @@ -11,6 +11,12 @@ EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ" LONGINT_IMPL = MPZ CIRCUITPY_AESIO = 0 -CIRCUITPY_JPEGIO = 0 -CIRCUITPY_SYNTHIO = 0 -CIRCUITPY_TILEPALETTEMAPPER = 0 +CIRCUITPY_CODEOP = 0 +CIRCUITPY_EPAPERDISPLAY = 0 +CIRCUITPY_FLOPPYIO = 0 +CIRCUITPY_I2CDISPLAYBUS = 0 +CIRCUITPY_I2CTARGET = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_SHARPDISPLAY = 0 +CIRCUITPY_SPITARGET = 0 diff --git a/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk b/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk index 82d7f0f43ba59..3ce42ed3a7e7e 100644 --- a/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk +++ b/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk @@ -9,6 +9,8 @@ CHIP_FAMILY = samd51 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY_I2CTARGET = 0 CIRCUITPY_SPITARGET = 0 CIRCUITPY_SYNTHIO = 0 CIRCUITPY_JPEGIO = 0 diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c index 705f8ceeb8bec..e8434717c4269 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c @@ -130,7 +130,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use")); } - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } diff --git a/ports/cxd56/common-hal/pulseio/PulseIn.c b/ports/cxd56/common-hal/pulseio/PulseIn.c index f0063d3f0d8c9..0c45cf850328b 100644 --- a/ports/cxd56/common-hal/pulseio/PulseIn.c +++ b/ports/cxd56/common-hal/pulseio/PulseIn.c @@ -65,7 +65,7 @@ static int pulsein_interrupt_handler(int irq, FAR void *context, FAR void *arg) void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu_pin_obj_t *pin, uint16_t maxlen, bool idle_state) { - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } diff --git a/ports/espressif/common-hal/_bleio/Characteristic.c b/ports/espressif/common-hal/_bleio/Characteristic.c index 6b842ad298cd1..7e917d6334b6b 100644 --- a/ports/espressif/common-hal/_bleio/Characteristic.c +++ b/ports/espressif/common-hal/_bleio/Characteristic.c @@ -78,7 +78,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, // If max_length is 0, then no storage is allocated. if (max_length > 0) { if (gc_alloc_possible()) { - self->current_value = m_malloc(max_length); + self->current_value = m_malloc_without_collect(max_length); } else { self->current_value = port_malloc(max_length, false); if (self->current_value == NULL) { diff --git a/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c b/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c index 8020af2873db6..3c0cbf323f3e2 100644 --- a/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c @@ -54,7 +54,7 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe bleio_characteristic_obj_t *characteristic, mp_float_t timeout, size_t buffer_size) { - uint8_t *buffer = m_malloc(buffer_size); + uint8_t *buffer = m_malloc_without_collect(buffer_size); _common_hal_bleio_characteristic_buffer_construct(self, characteristic, timeout, buffer, buffer_size, NULL, false); } diff --git a/ports/espressif/common-hal/_bleio/PacketBuffer.c b/ports/espressif/common-hal/_bleio/PacketBuffer.c index 1cc167cb5c80d..db035157ceb6b 100644 --- a/ports/espressif/common-hal/_bleio/PacketBuffer.c +++ b/ports/espressif/common-hal/_bleio/PacketBuffer.c @@ -240,17 +240,17 @@ void common_hal_bleio_packet_buffer_construct( uint32_t *incoming_buffer = NULL; if (incoming) { incoming_buffer_size = buffer_size * (sizeof(uint16_t) + max_packet_size); - incoming_buffer = m_malloc(incoming_buffer_size); + incoming_buffer = m_malloc_without_collect(incoming_buffer_size); } uint32_t *outgoing1 = NULL; uint32_t *outgoing2 = NULL; if (outgoing) { - outgoing1 = m_malloc(max_packet_size); + outgoing1 = m_malloc_without_collect(max_packet_size); // Only allocate the second buffer if we are doing writes with responses. // Without responses, we just write as quickly as we can. if (outgoing == CHAR_PROP_WRITE || outgoing == CHAR_PROP_INDICATE) { - outgoing2 = m_malloc(max_packet_size); + outgoing2 = m_malloc_without_collect(max_packet_size); } } _common_hal_bleio_packet_buffer_construct(self, characteristic, diff --git a/ports/espressif/common-hal/_bleio/ble_events.c b/ports/espressif/common-hal/_bleio/ble_events.c index 6a616819a8bd3..5b9eb649c977e 100644 --- a/ports/espressif/common-hal/_bleio/ble_events.c +++ b/ports/espressif/common-hal/_bleio/ble_events.c @@ -64,7 +64,7 @@ void ble_event_add_handler(ble_gap_event_fn *func, void *param) { } // Add a new handler to the front of the list - ble_event_handler_entry_t *handler = m_new(ble_event_handler_entry_t, 1); + ble_event_handler_entry_t *handler = m_new_obj(ble_event_handler_entry_t); ble_event_add_handler_entry(handler, func, param); } diff --git a/ports/espressif/common-hal/audioio/AudioOut.c b/ports/espressif/common-hal/audioio/AudioOut.c index 6d829228e1555..fb8c862ba0701 100644 --- a/ports/espressif/common-hal/audioio/AudioOut.c +++ b/ports/espressif/common-hal/audioio/AudioOut.c @@ -42,7 +42,7 @@ static bool audioout_convert_u8s_u8m( bool buffer_changed = false; if (in_buffer_size / 2 > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size / 2); + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); buffer_changed = true; } audiosample_convert_u8s_u8m(*out_buffer, (uint8_t *)in_buffer, in_buffer_size / 2); @@ -58,7 +58,7 @@ static bool audioout_convert_u8m_u8s( bool buffer_changed = false; if (in_buffer_size * 2 > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size * 2); + *out_buffer = m_malloc_without_collect(in_buffer_size * 2); buffer_changed = true; } audiosample_convert_u8m_u8s(*out_buffer, (uint8_t *)in_buffer, in_buffer_size); @@ -74,7 +74,7 @@ static bool audioout_convert_s8m_u8m( bool buffer_changed = false; if (in_buffer_size > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size); + *out_buffer = m_malloc_without_collect(in_buffer_size); buffer_changed = true; } audiosample_convert_s8m_u8m(*out_buffer, (int8_t *)in_buffer, in_buffer_size); @@ -90,7 +90,7 @@ static bool audioout_convert_s8s_u8m( bool buffer_changed = false; if (in_buffer_size / 2 > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size / 2); + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); buffer_changed = true; } audiosample_convert_s8s_u8m(*out_buffer, (int8_t *)in_buffer, in_buffer_size / 2); @@ -106,7 +106,7 @@ static bool audioout_convert_s8m_u8s( bool buffer_changed = false; if (in_buffer_size * 2 > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size * 2); + *out_buffer = m_malloc_without_collect(in_buffer_size * 2); buffer_changed = true; } audiosample_convert_s8m_u8s(*out_buffer, (int8_t *)in_buffer, in_buffer_size); @@ -122,7 +122,7 @@ static bool audioout_convert_s8s_u8s( bool buffer_changed = false; if (in_buffer_size > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size); + *out_buffer = m_malloc_without_collect(in_buffer_size); buffer_changed = true; } audiosample_convert_s8s_u8s(*out_buffer, (int8_t *)in_buffer, in_buffer_size); @@ -138,7 +138,7 @@ static bool audioout_convert_u16m_u8m( bool buffer_changed = false; if (in_buffer_size / 2 > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size / 2); + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); buffer_changed = true; } audiosample_convert_u16m_u8m(*out_buffer, (uint16_t *)in_buffer, in_buffer_size / 2); @@ -154,7 +154,7 @@ static bool audioout_convert_u16m_u8s( bool buffer_changed = false; if (in_buffer_size > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size); + *out_buffer = m_malloc_without_collect(in_buffer_size); buffer_changed = true; } audiosample_convert_u16m_u8s(*out_buffer, (uint16_t *)in_buffer, in_buffer_size / 2); @@ -186,7 +186,7 @@ static bool audioout_convert_u16s_u8s( bool buffer_changed = false; if (in_buffer_size / 2 > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size / 2); + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); buffer_changed = true; } audiosample_convert_u16s_u8s(*out_buffer, (uint16_t *)in_buffer, in_buffer_size / 4); @@ -202,7 +202,7 @@ static bool audioout_convert_s16m_u8m( bool buffer_changed = false; if (in_buffer_size / 2 > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size / 2); + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); buffer_changed = true; } audiosample_convert_s16m_u8m(*out_buffer, (int16_t *)in_buffer, in_buffer_size / 2); @@ -218,7 +218,7 @@ static bool audioout_convert_s16m_u8s( bool buffer_changed = false; if (in_buffer_size > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size); + *out_buffer = m_malloc_without_collect(in_buffer_size); buffer_changed = true; } audiosample_convert_s16m_u8s(*out_buffer, (int16_t *)in_buffer, in_buffer_size / 2); @@ -250,7 +250,7 @@ static bool audioout_convert_s16s_u8s( bool buffer_changed = false; if (in_buffer_size / 2 > *out_buffer_size) { - *out_buffer = m_malloc(in_buffer_size / 2); + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); buffer_changed = true; } audiosample_convert_s16s_u8s(*out_buffer, (int16_t *)in_buffer, in_buffer_size / 4); diff --git a/ports/espressif/common-hal/nvm/ByteArray.c b/ports/espressif/common-hal/nvm/ByteArray.c index adea91411b6f7..971f9bc7991be 100644 --- a/ports/espressif/common-hal/nvm/ByteArray.c +++ b/ports/espressif/common-hal/nvm/ByteArray.c @@ -46,7 +46,7 @@ static esp_err_t get_bytes(nvs_handle_t handle, uint8_t **buf_out) { *buf_out = NULL; return result; } - buf = m_malloc(size); // this SHOULD be the same as + buf = m_malloc_without_collect(size); // this SHOULD be the same as if (result == ESP_OK) { result = nvs_get_blob(handle, "data", buf, &size); } else { diff --git a/ports/espressif/common-hal/pulseio/PulseIn.c b/ports/espressif/common-hal/pulseio/PulseIn.c index 79d003a8a1e87..f7e500790562a 100644 --- a/ports/espressif/common-hal/pulseio/PulseIn.c +++ b/ports/espressif/common-hal/pulseio/PulseIn.c @@ -74,14 +74,14 @@ static bool _done_callback(rmt_channel_handle_t rx_chan, void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu_pin_obj_t *pin, uint16_t maxlen, bool idle_state) { - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } // We add one to the maxlen version to ensure that two symbols at lease are // captured because we may skip the first portion of a symbol. self->raw_symbols_size = MIN(64, maxlen / 2 + 1) * sizeof(rmt_symbol_word_t); - self->raw_symbols = (rmt_symbol_word_t *)m_malloc(self->raw_symbols_size); + self->raw_symbols = (rmt_symbol_word_t *)m_malloc_without_collect(self->raw_symbols_size); if (self->raw_symbols == NULL) { m_free(self->buffer); m_malloc_fail(self->raw_symbols_size); diff --git a/ports/espressif/mpconfigport.h b/ports/espressif/mpconfigport.h index 98c1986240b73..712eb67f1f42a 100644 --- a/ports/espressif/mpconfigport.h +++ b/ports/espressif/mpconfigport.h @@ -22,6 +22,9 @@ #define MICROPY_NLR_SETJMP (1) #define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 +// PSRAM can require more stack space for GC. +#define MICROPY_ALLOC_GC_STACK_SIZE (128) + // Nearly all boards have this because it is used to enter the ROM bootloader. #ifndef CIRCUITPY_BOOT_BUTTON #if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) diff --git a/ports/mimxrt10xx/common-hal/audiobusio/__init__.c b/ports/mimxrt10xx/common-hal/audiobusio/__init__.c index 2430b6bdaa637..196e52dbf0369 100644 --- a/ports/mimxrt10xx/common-hal/audiobusio/__init__.c +++ b/ports/mimxrt10xx/common-hal/audiobusio/__init__.c @@ -309,7 +309,7 @@ void port_i2s_initialize(i2s_t *self, int instance, sai_transceiver_t *config) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_I2SOut); } for (size_t i = 0; i < MP_ARRAY_SIZE(self->buffers); i++) { - self->buffers[i] = m_malloc(AUDIO_BUFFER_FRAME_COUNT * sizeof(uint32_t)); + self->buffers[i] = m_malloc_without_collect(AUDIO_BUFFER_FRAME_COUNT * sizeof(uint32_t)); } self->peripheral = peripheral; SAI_Init(self->peripheral); diff --git a/ports/mimxrt10xx/common-hal/canio/CAN.c b/ports/mimxrt10xx/common-hal/canio/CAN.c index ba2c2482a34b9..0b598af1521f0 100644 --- a/ports/mimxrt10xx/common-hal/canio/CAN.c +++ b/ports/mimxrt10xx/common-hal/canio/CAN.c @@ -228,7 +228,7 @@ void common_hal_canio_can_construct(canio_can_obj_t *self, const mcu_pin_obj_t * self->silent = silent; self->baudrate = baudrate; - self->data = m_new_obj(mimxrt10xx_flexcan_data_t); + self->data = m_malloc_without_collect(sizeof(mimxrt10xx_flexcan_data_t)); self->data->base = flexcan_bases[instance]; // 'flexcan_bases' start indexing from 1. (The first element is NULL) self->data->tx_state = 0; diff --git a/ports/mimxrt10xx/common-hal/canio/Listener.c b/ports/mimxrt10xx/common-hal/canio/Listener.c index c2812b8b99345..e635549983411 100644 --- a/ports/mimxrt10xx/common-hal/canio/Listener.c +++ b/ports/mimxrt10xx/common-hal/canio/Listener.c @@ -123,7 +123,13 @@ mp_obj_t common_hal_canio_listener_receive(canio_listener_obj_t *self) { // allows the CPU to serve the next FIFO entry FLEXCAN_ClearMbStatusFlags(self->can->data->base, (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag); - canio_message_obj_t *message = m_new_obj(canio_message_obj_t); + const mp_obj_type_t *type; + if (rx_frame.type == kFLEXCAN_FrameTypeRemote) { + type = &canio_remote_transmission_request_type; + } else { + type = &canio_message_type; + } + canio_message_obj_t *message = mp_obj_malloc(canio_message_obj_t, type); memset(message, 0, sizeof(canio_message_obj_t)); if (rx_frame.format == kFLEXCAN_FrameFormatExtend) { @@ -134,11 +140,6 @@ mp_obj_t common_hal_canio_listener_receive(canio_listener_obj_t *self) { message->id = rx_frame.id >> 18; // standard ids are left-aligned } - if (rx_frame.type == kFLEXCAN_FrameTypeRemote) { - message->base.type = &canio_remote_transmission_request_type; - } else { - message->base.type = &canio_message_type; - } message->size = rx_frame.length; diff --git a/ports/nordic/common-hal/_bleio/Adapter.c b/ports/nordic/common-hal/_bleio/Adapter.c index b252cc49e58e2..9cf40ae91b3ff 100644 --- a/ports/nordic/common-hal/_bleio/Adapter.c +++ b/ports/nordic/common-hal/_bleio/Adapter.c @@ -524,7 +524,7 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t } self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi); size_t max_packet_size = extended ? BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED : BLE_GAP_SCAN_BUFFER_MAX; - uint8_t *raw_data = m_malloc(sizeof(ble_data_t) + max_packet_size); + uint8_t *raw_data = m_malloc_without_collect(sizeof(ble_data_t) + max_packet_size); ble_data_t *sd_data = (ble_data_t *)raw_data; self->scan_results->common_hal_data = sd_data; sd_data->len = max_packet_size; diff --git a/ports/nordic/common-hal/_bleio/Characteristic.c b/ports/nordic/common-hal/_bleio/Characteristic.c index 33a373f76c475..1975c2c3d79ce 100644 --- a/ports/nordic/common-hal/_bleio/Characteristic.c +++ b/ports/nordic/common-hal/_bleio/Characteristic.c @@ -81,7 +81,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->initial_value_len = initial_value_bufinfo->len; if (gc_alloc_possible()) { if (gc_nbytes(initial_value_bufinfo->buf) > 0) { - uint8_t *initial_value = m_malloc(self->initial_value_len); + uint8_t *initial_value = m_malloc_without_collect(self->initial_value_len); memcpy(initial_value, initial_value_bufinfo->buf, self->initial_value_len); self->initial_value = initial_value; } else { diff --git a/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c b/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c index 9a86afb39ac3b..6d1b9b550efc1 100644 --- a/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c @@ -97,7 +97,7 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe bleio_characteristic_obj_t *characteristic, mp_float_t timeout, size_t buffer_size) { - uint8_t *buffer = m_malloc(buffer_size); + uint8_t *buffer = m_malloc_without_collect(buffer_size); _common_hal_bleio_characteristic_buffer_construct(self, characteristic, timeout, buffer, buffer_size, NULL, false); } diff --git a/ports/nordic/common-hal/_bleio/PacketBuffer.c b/ports/nordic/common-hal/_bleio/PacketBuffer.c index db4307279ae10..6b3e86e3b7aac 100644 --- a/ports/nordic/common-hal/_bleio/PacketBuffer.c +++ b/ports/nordic/common-hal/_bleio/PacketBuffer.c @@ -278,14 +278,14 @@ void common_hal_bleio_packet_buffer_construct( uint32_t *incoming_buffer = NULL; if (incoming) { incoming_buffer_size = buffer_size * (sizeof(uint16_t) + max_packet_size); - incoming_buffer = m_malloc(incoming_buffer_size); + incoming_buffer = m_malloc_without_collect(incoming_buffer_size); } uint32_t *outgoing1 = NULL; uint32_t *outgoing2 = NULL; if (outgoing) { - outgoing1 = m_malloc(max_packet_size); - outgoing2 = m_malloc(max_packet_size); + outgoing1 = m_malloc_without_collect(max_packet_size); + outgoing2 = m_malloc_without_collect(max_packet_size); } _common_hal_bleio_packet_buffer_construct(self, characteristic, incoming_buffer, incoming_buffer_size, diff --git a/ports/nordic/common-hal/audiobusio/I2SOut.c b/ports/nordic/common-hal/audiobusio/I2SOut.c index 01758ee9b21e1..249b4f9d116f7 100644 --- a/ports/nordic/common-hal/audiobusio/I2SOut.c +++ b/ports/nordic/common-hal/audiobusio/I2SOut.c @@ -269,8 +269,8 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, self->buffer_length = sample_rate * buffer_length_ms * self->bytes_per_sample * self->channel_count / 1000; self->buffer_length = (self->buffer_length + 3) & ~3; - self->buffers[0] = m_malloc(self->buffer_length); - self->buffers[1] = m_malloc(self->buffer_length); + self->buffers[0] = m_malloc_without_collect(self->buffer_length); + self->buffers[1] = m_malloc_without_collect(self->buffer_length); audiosample_reset_buffer(self->sample, false, 0); diff --git a/ports/nordic/common-hal/audiopwmio/PWMAudioOut.c b/ports/nordic/common-hal/audiopwmio/PWMAudioOut.c index 03e959ed13999..53be11bcd7485 100644 --- a/ports/nordic/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/nordic/common-hal/audiopwmio/PWMAudioOut.c @@ -253,13 +253,13 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, size_t buffer_size = (size_t)max_buffer_length * 2 * sizeof(uint16_t); - self->buffers[0] = m_malloc(buffer_size); + self->buffers[0] = m_malloc_without_collect(buffer_size); #if MICROPY_MALLOC_USES_ALLOCATED_SIZE self->buffer_size[0] = buffer_size; #endif if (!self->single_buffer) { - self->buffers[1] = m_malloc(buffer_size); + self->buffers[1] = m_malloc_without_collect(buffer_size); #if MICROPY_MALLOC_USES_ALLOCATED_SIZE self->buffer_size[1] = buffer_size; #endif diff --git a/ports/nordic/common-hal/busio/UART.c b/ports/nordic/common-hal/busio/UART.c index c9b0024db921d..0dfe6ae3f5de2 100644 --- a/ports/nordic/common-hal/busio/UART.c +++ b/ports/nordic/common-hal/busio/UART.c @@ -325,7 +325,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, if (!nrfx_is_in_ram(data)) { // Allocate long strings on the heap. if (len > 128 && gc_alloc_possible()) { - tx_buf = (uint8_t *)m_malloc(len); + tx_buf = (uint8_t *)m_malloc_without_collect(len); } else { tx_buf = alloca(len); } diff --git a/ports/nordic/common-hal/pulseio/PulseIn.c b/ports/nordic/common-hal/pulseio/PulseIn.c index 0a2286090e0ed..dce3a9c96c1f5 100644 --- a/ports/nordic/common-hal/pulseio/PulseIn.c +++ b/ports/nordic/common-hal/pulseio/PulseIn.c @@ -98,7 +98,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu } _objs[idx] = self; - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } diff --git a/ports/raspberrypi/boards/adafruit_fruit_jam/board.c b/ports/raspberrypi/boards/adafruit_fruit_jam/board.c index 38fbde53f6ce3..a868bc02b7167 100644 --- a/ports/raspberrypi/boards/adafruit_fruit_jam/board.c +++ b/ports/raspberrypi/boards/adafruit_fruit_jam/board.c @@ -16,8 +16,8 @@ #define I2S_RESET_PIN_NUMBER 22 -#if defined(DEFAULT_USB_HOST_5V_POWER) bool board_reset_pin_number(uint8_t pin_number) { + #if defined(DEFAULT_USB_HOST_5V_POWER) if (pin_number == DEFAULT_USB_HOST_5V_POWER->number) { // doing this (rather than gpio_init) in this specific order ensures no // glitch if pin was already configured as a high output. gpio_init() temporarily @@ -29,6 +29,7 @@ bool board_reset_pin_number(uint8_t pin_number) { return true; } + #endif // Set I2S out of reset. if (pin_number == I2S_RESET_PIN_NUMBER) { gpio_put(pin_number, 1); @@ -39,7 +40,6 @@ bool board_reset_pin_number(uint8_t pin_number) { } return false; } -#endif void board_init(void) { // Reset the DAC to put it in a known state. diff --git a/ports/raspberrypi/common-hal/mdns/Server.c b/ports/raspberrypi/common-hal/mdns/Server.c index 4c87dd4664077..ac0c73389b1a5 100644 --- a/ports/raspberrypi/common-hal/mdns/Server.c +++ b/ports/raspberrypi/common-hal/mdns/Server.c @@ -211,7 +211,7 @@ static void alloc_search_result_cb(struct mdns_answer *answer, const char *varpa if ((flags & MDNS_SEARCH_RESULT_FIRST) != 0) { // first - mdns_remoteservice_obj_t *service = m_malloc(sizeof(mdns_remoteservice_obj_t)); + mdns_remoteservice_obj_t *service = m_malloc_maybe(sizeof(mdns_remoteservice_obj_t)); if (service == NULL) { // alloc fails mdns_search_stop(state->request_id); diff --git a/ports/raspberrypi/common-hal/pulseio/PulseIn.c b/ports/raspberrypi/common-hal/pulseio/PulseIn.c index b56c90a9a53bb..a2bfeec6c6a23 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseIn.c +++ b/ports/raspberrypi/common-hal/pulseio/PulseIn.c @@ -26,7 +26,7 @@ static const uint16_t pulsein_program[] = { void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu_pin_obj_t *pin, uint16_t maxlen, bool idle_state) { - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } diff --git a/ports/raspberrypi/common-hal/socketpool/Socket.c b/ports/raspberrypi/common-hal/socketpool/Socket.c index 086fc4a13f78f..018365def8c75 100644 --- a/ports/raspberrypi/common-hal/socketpool/Socket.c +++ b/ports/raspberrypi/common-hal/socketpool/Socket.c @@ -1071,7 +1071,8 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *socket, int ba socket->incoming.connection.tcp.item = NULL; } else { socket->incoming.connection.alloc = backlog; - socket->incoming.connection.tcp.array = m_new0(struct tcp_pcb *, backlog); + socket->incoming.connection.tcp.array = m_malloc_without_collect(sizeof(struct tcp_pcb *) * backlog); + memset(socket->incoming.connection.tcp.array, 0, sizeof(struct tcp_pcb *) * backlog); } socket->incoming.connection.iget = 0; socket->incoming.connection.iput = 0; diff --git a/ports/raspberrypi/mpconfigport.h b/ports/raspberrypi/mpconfigport.h index aa20cd90b8378..3eb576de39e67 100644 --- a/ports/raspberrypi/mpconfigport.h +++ b/ports/raspberrypi/mpconfigport.h @@ -14,6 +14,9 @@ #ifdef PICO_RP2350 #define MICROPY_PY_SYS_PLATFORM "RP2350" + +// PSRAM can require more stack space for GC. +#define MICROPY_ALLOC_GC_STACK_SIZE (128) #endif // Setting a non-default value also requires a non-default link.ld diff --git a/ports/silabs/common-hal/_bleio/CharacteristicBuffer.c b/ports/silabs/common-hal/_bleio/CharacteristicBuffer.c index 2acb6b00fcab9..d6a64db3a2e95 100644 --- a/ports/silabs/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/silabs/common-hal/_bleio/CharacteristicBuffer.c @@ -87,7 +87,7 @@ void common_hal_bleio_characteristic_buffer_construct( mp_float_t timeout, size_t buffer_size) { - uint8_t *buffer = m_malloc(buffer_size); + uint8_t *buffer = m_malloc_without_collect(buffer_size); _common_hal_bleio_characteristic_buffer_construct(self, characteristic, timeout, diff --git a/ports/silabs/common-hal/_bleio/PacketBuffer.c b/ports/silabs/common-hal/_bleio/PacketBuffer.c index 1e5159fc6a205..1d2b140f7efef 100644 --- a/ports/silabs/common-hal/_bleio/PacketBuffer.c +++ b/ports/silabs/common-hal/_bleio/PacketBuffer.c @@ -223,12 +223,12 @@ void common_hal_bleio_packet_buffer_construct( if (incoming) { incoming_buffer_size = buffer_size * (sizeof(uint16_t) + max_packet_size); - incoming_buffer = m_malloc(incoming_buffer_size); + incoming_buffer = m_malloc_without_collect(incoming_buffer_size); } if (outgoing) { - outgoing1 = m_malloc(max_packet_size); - outgoing2 = m_malloc(max_packet_size); + outgoing1 = m_malloc_without_collect(max_packet_size); + outgoing2 = m_malloc_without_collect(max_packet_size); } _common_hal_bleio_packet_buffer_construct(self, characteristic, incoming_buffer, incoming_buffer_size, diff --git a/ports/silabs/common-hal/_bleio/__init__.c b/ports/silabs/common-hal/_bleio/__init__.c index 2905dc41e09cc..a9ad7b32c36ba 100644 --- a/ports/silabs/common-hal/_bleio/__init__.c +++ b/ports/silabs/common-hal/_bleio/__init__.c @@ -194,8 +194,7 @@ void sl_bt_on_event(sl_bt_msg_t *evt) { uuid = m_new_obj_maybe(bleio_uuid_obj_t); if (NULL == uuid) { osMutexRelease(bluetooth_connection_mutex_id); - mp_raise_bleio_BluetoothError( - MP_ERROR_TEXT("Create new service uuid obj fail")); + m_malloc_fail(sizeof(bleio_uuid_obj_t)); break; } uuid->base.type = &bleio_uuid_type; diff --git a/ports/stm/common-hal/audiopwmio/PWMAudioOut.c b/ports/stm/common-hal/audiopwmio/PWMAudioOut.c index 2099f8d36bf2c..a5cc11965fabb 100644 --- a/ports/stm/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/stm/common-hal/audiopwmio/PWMAudioOut.c @@ -279,14 +279,14 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, uint16_t buffer_length = (uint16_t)max_buffer_length / self->bytes_per_sample; size_t buffer_size = buffer_length * sizeof(uint16_t); - self->buffer[0] = m_malloc(buffer_size); + self->buffer[0] = m_malloc_without_collect(buffer_size); #if MICROPY_MALLOC_USES_ALLOCATED_SIZE self->buffer_size[0] = buffer_size; #endif self->buffer_ptr[0] = self->buffer_length[0] = 0; if (self->pin[1]) { - self->buffer[1] = m_malloc(buffer_size); + self->buffer[1] = m_malloc_without_collect(buffer_size); #if MICROPY_MALLOC_USES_ALLOCATED_SIZE self->buffer_size[1] = buffer_size; #endif diff --git a/ports/stm/common-hal/pulseio/PulseIn.c b/ports/stm/common-hal/pulseio/PulseIn.c index 593e01f9bb911..86d304af5f1d4 100644 --- a/ports/stm/common-hal/pulseio/PulseIn.c +++ b/ports/stm/common-hal/pulseio/PulseIn.c @@ -84,7 +84,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu } // Allocate pulse buffer - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { // TODO: free the EXTI here? m_malloc_fail(maxlen * sizeof(uint16_t)); diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index afc1c3a38d14a..185d4dcf3401c 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -112,6 +112,8 @@ typedef long mp_off_t; // Always enable GC. #define MICROPY_ENABLE_GC (1) +// CIRCUITPY-CHANGE +#define MICROPY_ENABLE_SELECTIVE_COLLECT (1) #if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) // Fall back to setjmp() implementation for discovery of GC pointers in registers. diff --git a/py/bc.h b/py/bc.h index 007897a028ed6..7658f66414f17 100644 --- a/py/bc.h +++ b/py/bc.h @@ -302,14 +302,16 @@ static inline void mp_module_context_alloc_tables(mp_module_context_t *context, #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE size_t nq = (n_qstr * sizeof(qstr_short_t) + sizeof(mp_uint_t) - 1) / sizeof(mp_uint_t); size_t no = n_obj; - mp_uint_t *mem = m_new(mp_uint_t, nq + no); + // CIRCUITPY-CHANGE + mp_uint_t *mem = m_malloc_items(nq + no); context->constants.qstr_table = (qstr_short_t *)mem; context->constants.obj_table = (mp_obj_t *)(mem + nq); #else if (n_obj == 0) { context->constants.obj_table = NULL; } else { - context->constants.obj_table = m_new(mp_obj_t, n_obj); + // CIRCUITPY-CHANGE + context->constants.obj_table = m_malloc_items(n_obj); } #endif } diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index d7a230bf61d46..d6658867b7d1d 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -62,6 +62,7 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_EMIT_X64 (0) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_ENABLE_SELECTIVE_COLLECT (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_PYSTACK (1) #define MICROPY_TRACKED_ALLOC (CIRCUITPY_SSL_MBEDTLS) diff --git a/py/emitbc.c b/py/emitbc.c index 05754cfabf65d..f23f9e07d8410 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -83,7 +83,8 @@ emit_t *emit_bc_new(mp_emit_common_t *emit_common) { void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels) { emit->max_num_labels = max_num_labels; - emit->label_offsets = m_new(size_t, emit->max_num_labels); + // CIRCUITPY-CHANGE: Don't collect the label offsets + emit->label_offsets = m_malloc_without_collect(sizeof(size_t) * emit->max_num_labels); } void emit_bc_free(emit_t *emit) { @@ -373,7 +374,8 @@ bool mp_emit_bc_end_pass(emit_t *emit) { // calculate size of total code-info + bytecode, in bytes emit->code_info_size = emit->code_info_offset; emit->bytecode_size = emit->bytecode_offset; - emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size); + // CIRCUITPY-CHANGE: Don't collect the bytecode or code info. + emit->code_base = m_malloc_without_collect(sizeof(byte) * (emit->code_info_size + emit->bytecode_size)); } else if (emit->pass == MP_PASS_EMIT) { // Code info and/or bytecode can shrink during this pass. diff --git a/py/gc.c b/py/gc.c index 5375218f3e900..c4febe7569fa8 100644 --- a/py/gc.c +++ b/py/gc.c @@ -39,6 +39,8 @@ // CIRCUITPY-CHANGE #include "supervisor/shared/safe_mode.h" +#include "supervisor/shared/serial.h" + #if CIRCUITPY_MEMORYMONITOR #include "shared-module/memorymonitor/__init__.h" #endif @@ -123,6 +125,16 @@ #define FTB_CLEAR(area, block) do { area->gc_finaliser_table_start[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0) #endif +// CIRCUITPY-CHANGE: Add selective collect table to skip scanning large buffers without pointers +// CTB = collect table byte +// if set, then the corresponding block should be collected during GC + +#define BLOCKS_PER_CTB (8) + +#define CTB_GET(area, block) ((area->gc_collect_table_start[(block) / BLOCKS_PER_CTB] >> ((block) & 7)) & 1) +#define CTB_SET(area, block) do { area->gc_collect_table_start[(block) / BLOCKS_PER_CTB] |= (1 << ((block) & 7)); } while (0) +#define CTB_CLEAR(area, block) do { area->gc_collect_table_start[(block) / BLOCKS_PER_CTB] &= (~(1 << ((block) & 7))); } while (0) + #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL #define GC_ENTER() mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1) #define GC_EXIT() mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex)) @@ -143,48 +155,66 @@ void __attribute__ ((noinline)) gc_log_change(uint32_t start_block, uint32_t len #pragma GCC pop_options #endif + // TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool static void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { - // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes): - // T = A + F + P + // CIRCUITPY-CHANGE: Updated calculation to include selective collect table + // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, C=collect table, P=pool; all in bytes): + // T = A + F + C + P // F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB + // C = A * BLOCKS_PER_ATB / BLOCKS_PER_CTB // P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK - // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK) + size_t total_byte_len = (byte *)end - (byte *)start; + + // Calculate the denominator for the alloc table size calculation + size_t bits_per_block = MP_BITS_PER_BYTE / BLOCKS_PER_ATB; // Start with bits for ATB + #if MICROPY_ENABLE_FINALISER - area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) - * MP_BITS_PER_BYTE - / ( - MP_BITS_PER_BYTE - + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB - + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK - ); - #else - area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) / (1 + MP_BITS_PER_BYTE / 2 * BYTES_PER_BLOCK); + bits_per_block += MP_BITS_PER_BYTE / BLOCKS_PER_FTB; // Add bits for FTB + #endif + + #if MICROPY_ENABLE_SELECTIVE_COLLECT + bits_per_block += MP_BITS_PER_BYTE / BLOCKS_PER_CTB; // Add bits for CTB #endif + bits_per_block += MP_BITS_PER_BYTE * BYTES_PER_BLOCK; // Add bits for the block itself + + // Calculate the allocation table size + size_t available_bits = (total_byte_len - ALLOC_TABLE_GAP_BYTE) * MP_BITS_PER_BYTE; + size_t blocks = available_bits / bits_per_block; + area->gc_alloc_table_byte_len = blocks / BLOCKS_PER_ATB; + + // Set up all the table pointers area->gc_alloc_table_start = (byte *)start; + byte *next_table = area->gc_alloc_table_start + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE; + // Total number of blocks in the pool + size_t gc_pool_block_len = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; + + // Calculate table sizes and set start pointers #if MICROPY_ENABLE_FINALISER - size_t gc_finaliser_table_byte_len = (area->gc_alloc_table_byte_len * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; - area->gc_finaliser_table_start = area->gc_alloc_table_start + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE; + size_t gc_finaliser_table_byte_len = (gc_pool_block_len + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; + area->gc_finaliser_table_start = next_table; + next_table += gc_finaliser_table_byte_len; #endif - size_t gc_pool_block_len = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; + #if MICROPY_ENABLE_SELECTIVE_COLLECT + size_t gc_collect_table_byte_len = (gc_pool_block_len + BLOCKS_PER_CTB - 1) / BLOCKS_PER_CTB; + area->gc_collect_table_start = next_table; + next_table += gc_collect_table_byte_len; + #endif + + // Set pool pointers area->gc_pool_start = (byte *)end - gc_pool_block_len * BYTES_PER_BLOCK; area->gc_pool_end = end; - #if MICROPY_ENABLE_FINALISER - assert(area->gc_pool_start >= area->gc_finaliser_table_start + gc_finaliser_table_byte_len); - #endif + // Verify enough space between last table and start of pool + assert(area->gc_pool_start >= next_table); - #if MICROPY_ENABLE_FINALISER - // clear ATB's and FTB's - memset(area->gc_alloc_table_start, 0, gc_finaliser_table_byte_len + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE); - #else - // clear ATB's - memset(area->gc_alloc_table_start, 0, area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE); - #endif + // Clear all tables + size_t tables_size = next_table - area->gc_alloc_table_start; + memset(area->gc_alloc_table_start, 0, tables_size); area->gc_last_free_atb_index = 0; area->gc_last_used_block = 0; @@ -204,6 +234,12 @@ static void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { gc_finaliser_table_byte_len, gc_finaliser_table_byte_len * BLOCKS_PER_FTB); #endif + #if MICROPY_ENABLE_SELECTIVE_COLLECT + DEBUG_printf(" collect table at %p, length " UINT_FMT " bytes, " + UINT_FMT " blocks\n", area->gc_collect_table_start, + gc_collect_table_byte_len, + gc_collect_table_byte_len * BLOCKS_PER_CTB); + #endif DEBUG_printf(" pool at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", area->gc_pool_start, gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len); @@ -261,16 +297,44 @@ void gc_add(void *start, void *end) { } #if MICROPY_GC_SPLIT_HEAP_AUTO +// CIRCUITPY-CHANGE: Added function to compute heap size with selective collect table +static size_t compute_heap_size(size_t total_blocks) { + // Add two blocks to account for allocation alignment. + total_blocks += 2; + size_t atb_bytes = (total_blocks + BLOCKS_PER_ATB - 1) / BLOCKS_PER_ATB; + size_t ftb_bytes = 0; + size_t ctb_bytes = 0; + #if MICROPY_ENABLE_FINALISER + ftb_bytes = (total_blocks + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; + #endif + #if MICROPY_ENABLE_SELECTIVE_COLLECT + ctb_bytes = (total_blocks + BLOCKS_PER_CTB - 1) / BLOCKS_PER_CTB; + #endif + size_t pool_bytes = total_blocks * BYTES_PER_BLOCK; + + // Compute bytes needed to build a heap with total_blocks blocks. + size_t total_heap = + atb_bytes + + ftb_bytes + + ctb_bytes + + pool_bytes + + ALLOC_TABLE_GAP_BYTE + + sizeof(mp_state_mem_area_t); + + // Round up size to the nearest multiple of BYTES_PER_BLOCK. + total_heap = (total_heap + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; + total_heap *= BYTES_PER_BLOCK; + return total_heap; +} + // Try to automatically add a heap area large enough to fulfill 'failed_alloc'. static bool gc_try_add_heap(size_t failed_alloc) { // 'needed' is the size of a heap large enough to hold failed_alloc, with // the additional metadata overheads as calculated in gc_setup_area(). - // - // Rather than reproduce all of that logic here, we approximate that adding - // (13/512) is enough overhead for sufficiently large heap areas (the - // overhead converges to 3/128, but there's some fixed overhead and some - // rounding up of partial block sizes). - size_t needed = failed_alloc + MAX(2048, failed_alloc * 13 / 512); + // CIRCUITPY-CHANGE: calculation of how much to grow the heap + size_t total_new_blocks = (failed_alloc + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; + // CIRCUITPY-CHANGE + size_t needed = compute_heap_size(total_new_blocks); size_t avail = gc_get_max_new_split(); @@ -314,18 +378,8 @@ static bool gc_try_add_heap(size_t failed_alloc) { total_blocks += area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; } - // Compute bytes needed to build a heap with total_blocks blocks. - size_t total_heap = - total_blocks / BLOCKS_PER_ATB - #if MICROPY_ENABLE_FINALISER - + total_blocks / BLOCKS_PER_FTB - #endif - + total_blocks * BYTES_PER_BLOCK - + ALLOC_TABLE_GAP_BYTE - + sizeof(mp_state_mem_area_t); - - // Round up size to the nearest multiple of BYTES_PER_BLOCK. - total_heap = (total_heap + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1)); + // CIRCUITPY-CHANGE + size_t total_heap = compute_heap_size(total_blocks); DEBUG_printf("total_heap " UINT_FMT " bytes\n", total_heap); @@ -447,41 +501,52 @@ static void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(size_t block) // check that the consecutive blocks didn't overflow past the end of the area assert(area->gc_pool_start + (block + n_blocks) * BYTES_PER_BLOCK <= area->gc_pool_end); - // check this block's children - void **ptrs = (void **)PTR_FROM_BLOCK(area, block); - for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) { - MICROPY_GC_HOOK_LOOP(i); - void *ptr = *ptrs; - // If this is a heap pointer that hasn't been marked, mark it and push - // it's children to the stack. - #if MICROPY_GC_SPLIT_HEAP - mp_state_mem_area_t *ptr_area = gc_get_ptr_area(ptr); - if (!ptr_area) { - // Not a heap-allocated pointer (might even be random data). - continue; - } - #else - if (!VERIFY_PTR(ptr)) { - continue; - } - mp_state_mem_area_t *ptr_area = area; - #endif - size_t ptr_block = BLOCK_FROM_PTR(ptr_area, ptr); - if (ATB_GET_KIND(ptr_area, ptr_block) != AT_HEAD) { - // This block is already marked. - continue; - } - // An unmarked head. Mark it, and push it on gc stack. - TRACE_MARK(ptr_block, ptr); - ATB_HEAD_TO_MARK(ptr_area, ptr_block); - if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { - MP_STATE_MEM(gc_block_stack)[sp] = ptr_block; + // CIRCUITPY-CHANGE + // check if this block should be collected + #if MICROPY_ENABLE_SELECTIVE_COLLECT + bool should_scan = CTB_GET(area, block); + #else + bool should_scan = true; + #endif + + // Only scan the block's children if it's not a leaf + if (should_scan) { + // check this block's children + void **ptrs = (void **)PTR_FROM_BLOCK(area, block); + for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) { + MICROPY_GC_HOOK_LOOP(i); + void *ptr = *ptrs; + // If this is a heap pointer that hasn't been marked, mark it and push + // it's children to the stack. #if MICROPY_GC_SPLIT_HEAP - MP_STATE_MEM(gc_area_stack)[sp] = ptr_area; + mp_state_mem_area_t *ptr_area = gc_get_ptr_area(ptr); + if (!ptr_area) { + // Not a heap-allocated pointer (might even be random data). + continue; + } + #else + if (!VERIFY_PTR(ptr)) { + continue; + } + mp_state_mem_area_t *ptr_area = area; #endif - sp += 1; - } else { - MP_STATE_MEM(gc_stack_overflow) = 1; + size_t ptr_block = BLOCK_FROM_PTR(ptr_area, ptr); + if (ATB_GET_KIND(ptr_area, ptr_block) != AT_HEAD) { + // This block is already marked. + continue; + } + // An unmarked head. Mark it, and push it on gc stack. + TRACE_MARK(ptr_block, ptr); + ATB_HEAD_TO_MARK(ptr_area, ptr_block); + if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { + MP_STATE_MEM(gc_block_stack)[sp] = ptr_block; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_area_stack)[sp] = ptr_area; + #endif + sp += 1; + } else { + MP_STATE_MEM(gc_stack_overflow) = 1; + } } } @@ -944,6 +1009,20 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { (void)has_finaliser; #endif + // CIRCUITPY-CHANGE + #if MICROPY_ENABLE_SELECTIVE_COLLECT + bool do_not_collect = (alloc_flags & GC_ALLOC_FLAG_DO_NOT_COLLECT) != 0; + GC_ENTER(); + if (do_not_collect) { + // Mark as not to be collected + CTB_CLEAR(area, start_block); + } else { + // By default, all blocks should be collected + CTB_SET(area, start_block); + } + GC_EXIT(); + #endif + #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(&mp_plat_print); #endif @@ -1110,7 +1189,8 @@ void *gc_realloc(void *ptr, mp_uint_t n_bytes) { void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // check for pure allocation if (ptr_in == NULL) { - return gc_alloc(n_bytes, false); + // CIRCUITPY-CHANGE + return gc_alloc(n_bytes, 0); } // check for pure free @@ -1248,10 +1328,18 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { return ptr_in; } + uint8_t alloc_flags = 0; #if MICROPY_ENABLE_FINALISER - bool ftb_state = FTB_GET(area, block); - #else - bool ftb_state = false; + if (FTB_GET(area, block)) { + alloc_flags |= GC_ALLOC_FLAG_HAS_FINALISER; + } + #endif + + // CIRCUITPY-CHANGE + #if MICROPY_ENABLE_SELECTIVE_COLLECT + if (!CTB_GET(area, block)) { + alloc_flags |= GC_ALLOC_FLAG_DO_NOT_COLLECT; + } #endif GC_EXIT(); @@ -1262,7 +1350,8 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { } // can't resize inplace; try to find a new contiguous chain - void *ptr_out = gc_alloc(n_bytes, ftb_state); + // CIRCUITPY-CHANGE + void *ptr_out = gc_alloc(n_bytes, alloc_flags); // check that the alloc succeeded if (ptr_out == NULL) { diff --git a/py/gc.h b/py/gc.h index 5f4b18f7e64bb..ebc32b080fb47 100644 --- a/py/gc.h +++ b/py/gc.h @@ -73,6 +73,10 @@ void gc_sweep_all(void); enum { GC_ALLOC_FLAG_HAS_FINALISER = 1, + // CIRCUITPY-CHANGE + #if MICROPY_ENABLE_SELECTIVE_COLLECT + GC_ALLOC_FLAG_DO_NOT_COLLECT = 2, + #endif }; void *gc_alloc(size_t n_bytes, unsigned int alloc_flags); diff --git a/py/malloc.c b/py/malloc.c index 60f0df7455d11..c83dd4bd6c7d1 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include #include #include @@ -53,11 +54,19 @@ // freely accessed - for interfacing with system and 3rd-party libs for // example. On the other hand, some (e.g. bare-metal) ports may use GC // heap as system heap, so, to avoid warnings, we do undef's first. +// CIRCUITPY-CHANGE: Add selective collect support to malloc to optimize GC for large buffers #undef malloc #undef free #undef realloc -#define malloc(b) gc_alloc((b), false) -#define malloc_with_finaliser(b) gc_alloc((b), true) +#if MICROPY_ENABLE_SELECTIVE_COLLECT +#define malloc(b) gc_alloc((b), GC_ALLOC_FLAG_DO_NOT_COLLECT) +#define malloc_with_collect(b) gc_alloc((b), 0) +#define malloc_without_collect(b) gc_alloc((b), GC_ALLOC_FLAG_DO_NOT_COLLECT) +#else +#define malloc(b) gc_alloc((b), 0) +#define malloc_with_collect(b) gc_alloc((b), 0) +#endif +#define malloc_with_finaliser(b) gc_alloc((b), GC_ALLOC_FLAG_HAS_FINALISER) #define free gc_free #define realloc(ptr, n) gc_realloc(ptr, n, true) #define realloc_ext(ptr, n, mv) gc_realloc(ptr, n, mv) @@ -69,6 +78,10 @@ #error MICROPY_ENABLE_FINALISER requires MICROPY_ENABLE_GC #endif +#if MICROPY_ENABLE_SELECTIVE_COLLECT +#error MICROPY_ENABLE_SELECTIVE_COLLECT requires MICROPY_ENABLE_GC +#endif + static void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) { if (allow_move) { return realloc(ptr, n_bytes); @@ -82,9 +95,23 @@ static void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) { #endif // MICROPY_ENABLE_GC -void *m_malloc(size_t num_bytes) { - void *ptr = malloc(num_bytes); - if (ptr == NULL && num_bytes != 0) { +// CIRCUITPY-CHANGE: Add malloc helper with flags instead of a list of bools. +void *m_malloc_helper(size_t num_bytes, uint8_t flags) { + void *ptr; + #if MICROPY_ENABLE_GC + #if MICROPY_ENABLE_SELECTIVE_COLLECT + if ((flags & M_MALLOC_COLLECT) == 0) { + ptr = malloc_without_collect(num_bytes); + } else { + ptr = malloc_with_collect(num_bytes); + } + #else + ptr = malloc_with_collect(num_bytes); + #endif + #else + ptr = malloc(num_bytes); + #endif + if (ptr == NULL && num_bytes != 0 && (flags & M_MALLOC_RAISE_ERROR)) { m_malloc_fail(num_bytes); } #if MICROPY_MEM_STATS @@ -92,44 +119,39 @@ void *m_malloc(size_t num_bytes) { MP_STATE_MEM(current_bytes_allocated) += num_bytes; UPDATE_PEAK(); #endif + // CIRCUITPY-CHANGE + // If this config is set then the GC clears all memory, so we don't need to. + #if !MICROPY_GC_CONSERVATIVE_CLEAR + if (flags & M_MALLOC_ENSURE_ZEROED) { + memset(ptr, 0, num_bytes); + } + #endif DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); return ptr; } -void *m_malloc_maybe(size_t num_bytes) { - void *ptr = malloc(num_bytes); - #if MICROPY_MEM_STATS - MP_STATE_MEM(total_bytes_allocated) += num_bytes; - MP_STATE_MEM(current_bytes_allocated) += num_bytes; - UPDATE_PEAK(); - #endif - DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); - return ptr; +void *m_malloc(size_t num_bytes) { + // CIRCUITPY-CHANGE + return m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); } -#if MICROPY_ENABLE_FINALISER -void *m_malloc_with_finaliser(size_t num_bytes) { - void *ptr = malloc_with_finaliser(num_bytes); - if (ptr == NULL && num_bytes != 0) { - m_malloc_fail(num_bytes); - } - #if MICROPY_MEM_STATS - MP_STATE_MEM(total_bytes_allocated) += num_bytes; - MP_STATE_MEM(current_bytes_allocated) += num_bytes; - UPDATE_PEAK(); - #endif - DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); - return ptr; +void *m_malloc_maybe(size_t num_bytes) { + // CIRCUITPY-CHANGE + return m_malloc_helper(num_bytes, M_MALLOC_COLLECT); } -#endif void *m_malloc0(size_t num_bytes) { - void *ptr = m_malloc(num_bytes); - // If this config is set then the GC clears all memory, so we don't need to. - #if !MICROPY_GC_CONSERVATIVE_CLEAR - memset(ptr, 0, num_bytes); - #endif - return ptr; + return m_malloc_helper(num_bytes, M_MALLOC_ENSURE_ZEROED | M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); +} + +void *m_malloc_without_collect(size_t num_bytes) { + // CIRCUITPY-CHANGE + return m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR); +} + +void *m_malloc_maybe_without_collect(size_t num_bytes) { + // CIRCUITPY-CHANGE + return m_malloc_helper(num_bytes, 0); } #if MICROPY_MALLOC_USES_ALLOCATED_SIZE diff --git a/py/map.c b/py/map.c index d40e3dc4d02d7..c434e0d0cddcc 100644 --- a/py/map.c +++ b/py/map.c @@ -86,13 +86,17 @@ static size_t get_hash_alloc_greater_or_equal_to(size_t x) { /******************************************************************************/ /* map */ +// CIRCUITPY-CHANGE: Helper for allocating tables of elements +#define malloc_table(num) m_new0(mp_map_elem_t, num) + void mp_map_init(mp_map_t *map, size_t n) { if (n == 0) { map->alloc = 0; map->table = NULL; } else { map->alloc = n; - map->table = m_new0(mp_map_elem_t, map->alloc); + // CIRCUITPY-CHANGE + map->table = malloc_table(map->alloc); } map->used = 0; map->all_keys_are_qstrs = 1; @@ -133,7 +137,8 @@ static void mp_map_rehash(mp_map_t *map) { size_t new_alloc = get_hash_alloc_greater_or_equal_to(map->alloc + 1); DEBUG_printf("mp_map_rehash(%p): " UINT_FMT " -> " UINT_FMT "\n", map, old_alloc, new_alloc); mp_map_elem_t *old_table = map->table; - mp_map_elem_t *new_table = m_new0(mp_map_elem_t, new_alloc); + // CIRCUITPY-CHANGE + mp_map_elem_t *new_table = malloc_table(new_alloc); // If we reach this point, table resizing succeeded, now we can edit the old map. map->alloc = new_alloc; map->used = 0; @@ -329,7 +334,8 @@ mp_map_elem_t *MICROPY_WRAP_MP_MAP_LOOKUP(mp_map_lookup)(mp_map_t * map, mp_obj_ void mp_set_init(mp_set_t *set, size_t n) { set->alloc = n; set->used = 0; - set->table = m_new0(mp_obj_t, set->alloc); + // CIRCUITPY-CHANGE + set->table = m_malloc_items0(set->alloc); } static void mp_set_rehash(mp_set_t *set) { @@ -337,7 +343,8 @@ static void mp_set_rehash(mp_set_t *set) { mp_obj_t *old_table = set->table; set->alloc = get_hash_alloc_greater_or_equal_to(set->alloc + 1); set->used = 0; - set->table = m_new0(mp_obj_t, set->alloc); + // CIRCUITPY-CHANGE + set->table = m_malloc_items0(set->alloc); for (size_t i = 0; i < old_alloc; i++) { if (old_table[i] != MP_OBJ_NULL && old_table[i] != MP_OBJ_SENTINEL) { mp_set_lookup(set, old_table[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); diff --git a/py/misc.h b/py/misc.h index 769d12ddbee5c..868faa412b4de 100644 --- a/py/misc.h +++ b/py/misc.h @@ -74,14 +74,23 @@ typedef unsigned int uint; // TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element) +// CIRCUITPY-CHANGE: new wrappers for selective collect, and use of m_malloc_helper() +// The following are convenience wrappers for m_malloc_helper and can save space at the call sites. +// m_malloc and m_new allocate space that is collected and does not have a finaliser. Use +// m_malloc_without_collect() if the space will not contain pointers to other heap allocations. It +// will still be marked and swept but not scanned for other pointers. +// Use m_malloc_items() to allocate space for mp_obj_ts that will be collected. +// Use mp_obj_malloc*() to allocate space for objects (aka structs with a type pointer) that will be +// collected. + #define m_new(type, num) ((type *)(m_malloc(sizeof(type) * (num)))) #define m_new_maybe(type, num) ((type *)(m_malloc_maybe(sizeof(type) * (num)))) #define m_new0(type, num) ((type *)(m_malloc0(sizeof(type) * (num)))) #define m_new_obj(type) (m_new(type, 1)) #define m_new_obj_maybe(type) (m_new_maybe(type, 1)) -#define m_new_obj_var(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) -#define m_new_obj_var0(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc0(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) -#define m_new_obj_var_maybe(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_maybe(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) +#define m_new_obj_var(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_helper(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num), M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT)) +#define m_new_obj_var0(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_helper(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num), M_MALLOC_ENSURE_ZEROED | M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT)) +#define m_new_obj_var_maybe(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_helper(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num), M_MALLOC_COLLECT)) #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num)))) #define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num), (allow_move)))) @@ -95,10 +104,21 @@ typedef unsigned int uint; #endif #define m_del_obj(type, ptr) (m_del(type, ptr, 1)) +#define m_malloc_items(num) m_malloc(sizeof(mp_obj_t) * (num)) +#define m_malloc_items0(num) m_malloc0(sizeof(mp_obj_t) * (num)) + +// Flags for m_malloc_helper +#define M_MALLOC_ENSURE_ZEROED (1 << 0) +#define M_MALLOC_RAISE_ERROR (1 << 1) +#define M_MALLOC_COLLECT (1 << 2) +#define M_MALLOC_WITH_FINALISER (1 << 3) + +void *m_malloc_helper(size_t num_bytes, uint8_t flags); void *m_malloc(size_t num_bytes); void *m_malloc_maybe(size_t num_bytes); -void *m_malloc_with_finaliser(size_t num_bytes); void *m_malloc0(size_t num_bytes); +void *m_malloc_without_collect(size_t num_bytes); +void *m_malloc_maybe_without_collect(size_t num_bytes); #if MICROPY_MALLOC_USES_ALLOCATED_SIZE void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes); void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes, bool allow_move); diff --git a/py/mpstate.h b/py/mpstate.h index 7308e57b58193..1fcc759da79bc 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -100,6 +100,10 @@ typedef struct _mp_state_mem_area_t { #if MICROPY_ENABLE_FINALISER byte *gc_finaliser_table_start; #endif + // CIRCUITPY-CHANGE + #if MICROPY_ENABLE_SELECTIVE_COLLECT + byte *gc_collect_table_start; + #endif byte *gc_pool_start; byte *gc_pool_end; diff --git a/py/obj.c b/py/obj.c index a825efc3c5a8f..20554aaccefdf 100644 --- a/py/obj.c +++ b/py/obj.c @@ -31,6 +31,7 @@ // CIRCUITPY-CHANGE #include "shared/runtime/interrupt_char.h" +#include "py/misc.h" #include "py/obj.h" #include "py/objtype.h" #include "py/objint.h" @@ -46,7 +47,8 @@ // Allocates an object and also sets type, for mp_obj_malloc{,_var} macros. MP_NOINLINE void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type) { - mp_obj_base_t *base = (mp_obj_base_t *)m_malloc(num_bytes); + // CIRCUITPY-CHANGE + mp_obj_base_t *base = (mp_obj_base_t *)m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); base->type = type; return base; } @@ -54,7 +56,8 @@ MP_NOINLINE void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *ty #if MICROPY_ENABLE_FINALISER // Allocates an object and also sets type, for mp_obj_malloc{,_var}_with_finaliser macros. MP_NOINLINE void *mp_obj_malloc_with_finaliser_helper(size_t num_bytes, const mp_obj_type_t *type) { - mp_obj_base_t *base = (mp_obj_base_t *)m_malloc_with_finaliser(num_bytes); + // CIRCUITPY-CHANGE + mp_obj_base_t *base = (mp_obj_base_t *)m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT | M_MALLOC_WITH_FINALISER); base->type = type; return base; } diff --git a/py/objarray.c b/py/objarray.c index 3ab982184f9bb..f43a69cfb4d2c 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -105,18 +105,22 @@ static mp_obj_array_t *array_new(char typecode, size_t n) { mp_raise_ValueError(MP_ERROR_TEXT("bad typecode")); } int typecode_size = mp_binary_get_size('@', typecode, NULL); - mp_obj_array_t *o = m_new_obj(mp_obj_array_t); + + // CIRCUITPY-CHANGE: refactor to use m_obj_malloc() + const mp_obj_type_t *type; #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY - o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array; + type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array; #elif MICROPY_PY_BUILTINS_BYTEARRAY - o->base.type = &mp_type_bytearray; + type = &mp_type_bytearray; #else - o->base.type = &mp_type_array; + type = &mp_type_array; #endif + mp_obj_array_t *o = mp_obj_malloc(mp_obj_array_t, type); o->typecode = typecode; o->free = 0; o->len = n; - o->items = m_new(byte, typecode_size * o->len); + // CIRCUITPY-CHANGE + o->items = m_malloc_without_collect(typecode_size * o->len); return o; } #endif @@ -225,7 +229,8 @@ static mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, #if MICROPY_PY_BUILTINS_MEMORYVIEW mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items) { - mp_obj_array_t *self = m_new_obj(mp_obj_array_t); + // CIRCUITPY-CHANGE + mp_obj_array_t *self = mp_obj_malloc(mp_obj_array_t, &mp_type_memoryview); mp_obj_memoryview_init(self, typecode, 0, nitems, items); return MP_OBJ_FROM_PTR(self); } @@ -684,7 +689,8 @@ static mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value if (slice.start > memview_offset_max) { mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("memoryview offset too large")); } - res = m_new_obj(mp_obj_array_t); + // CIRCUITPY-CHANGE + res = mp_obj_malloc(mp_obj_array_t, &mp_type_memoryview); *res = *o; res->memview_offset += slice.start; res->len = slice.stop - slice.start; diff --git a/py/objclosure.c b/py/objclosure.c index 3ba507b959382..5235312b519bf 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -50,7 +50,8 @@ static mp_obj_t closure_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const return mp_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2); } else { // use heap to allocate temporary args array - mp_obj_t *args2 = m_new(mp_obj_t, n_total); + // CIRCUITPY-CHANGE + mp_obj_t *args2 = m_malloc_items(n_total); memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t)); memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); mp_obj_t res = mp_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2); diff --git a/py/objdeque.c b/py/objdeque.c index 583537017fdb2..2edb6908f0b4c 100644 --- a/py/objdeque.c +++ b/py/objdeque.c @@ -58,7 +58,8 @@ static mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t mp_obj_deque_t *o = mp_obj_malloc(mp_obj_deque_t, type); o->alloc = maxlen + 1; o->i_get = o->i_put = 0; - o->items = m_new0(mp_obj_t, o->alloc); + // CIRCUITPY-CHANGE + o->items = m_malloc_items(o->alloc); if (n_args > 2) { o->flags = mp_obj_get_int(args[2]); diff --git a/py/objdict.c b/py/objdict.c index 7094a1c1f99f2..79a606f09707b 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -747,7 +747,8 @@ void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args) { } mp_obj_t mp_obj_new_dict(size_t n_args) { - mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t); + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_dict_t *o = mp_obj_malloc(mp_obj_dict_t, &mp_type_dict); mp_obj_dict_init(o, n_args); return MP_OBJ_FROM_PTR(o); } diff --git a/py/objfloat.c b/py/objfloat.c index 6f248cdadfc9e..fa5a26b438b45 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -198,9 +198,8 @@ MP_DEFINE_CONST_OBJ_TYPE( #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D mp_obj_t mp_obj_new_float(mp_float_t value) { - // Don't use mp_obj_malloc here to avoid extra function call overhead. - mp_obj_float_t *o = m_new_obj(mp_obj_float_t); - o->base.type = &mp_type_float; + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_float_t *o = mp_obj_malloc(mp_obj_float_t, &mp_type_float); o->value = value; return MP_OBJ_FROM_PTR(o); } diff --git a/py/objlist.c b/py/objlist.c index 2c1545d877715..d0b6fd4b3e47e 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -504,12 +504,14 @@ void mp_obj_list_init(mp_obj_list_t *o, size_t n) { o->base.type = &mp_type_list; o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n; o->len = n; - o->items = m_new(mp_obj_t, o->alloc); + // CIRCUITPY-CHANGE: Use m_malloc_items because these are mp_obj_t + o->items = m_malloc_items(o->alloc); mp_seq_clear(o->items, n, o->alloc, sizeof(*o->items)); } static mp_obj_list_t *list_new(size_t n) { - mp_obj_list_t *o = m_new_obj(mp_obj_list_t); + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_list_t *o = mp_obj_malloc(mp_obj_list_t, &mp_type_list); mp_obj_list_init(o, n); return o; } diff --git a/py/objmap.c b/py/objmap.c index 1911a7510abe8..d8042f867c73b 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -50,7 +50,8 @@ static mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ static mp_obj_t map_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_map)); mp_obj_map_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters); + // CIRCUITPY-CHANGE: Use m_malloc_items because it is an array of objects + mp_obj_t *nextses = m_malloc_items(self->n_iters); for (size_t i = 0; i < self->n_iters; i++) { mp_obj_t next = mp_iternext(self->iters[i]); diff --git a/py/objmodule.c b/py/objmodule.c index 3ccd31b23af22..a5c1dee968ea8 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -134,8 +134,8 @@ mp_obj_t mp_obj_new_module(qstr module_name) { } // create new module object - mp_module_context_t *o = m_new_obj(mp_module_context_t); - o->module.base.type = &mp_type_module; + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_module_context_t *o = mp_obj_malloc(mp_module_context_t, &mp_type_module); o->module.globals = MP_OBJ_TO_PTR(mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE)); // store __name__ entry in the module diff --git a/py/objproperty.c b/py/objproperty.c index a3a13a71bb3a3..96563f6dba389 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -57,7 +57,8 @@ static mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size } static mp_obj_t property_getter(mp_obj_t self_in, mp_obj_t getter) { - mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_property_t *p2 = mp_obj_malloc(mp_obj_property_t, &mp_type_property); *p2 = *(mp_obj_property_t *)MP_OBJ_TO_PTR(self_in); p2->proxy[0] = getter; return MP_OBJ_FROM_PTR(p2); @@ -66,7 +67,8 @@ static mp_obj_t property_getter(mp_obj_t self_in, mp_obj_t getter) { static MP_DEFINE_CONST_FUN_OBJ_2(property_getter_obj, property_getter); static mp_obj_t property_setter(mp_obj_t self_in, mp_obj_t setter) { - mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_property_t *p2 = mp_obj_malloc(mp_obj_property_t, &mp_type_property); *p2 = *(mp_obj_property_t *)MP_OBJ_TO_PTR(self_in); p2->proxy[1] = setter; return MP_OBJ_FROM_PTR(p2); @@ -75,7 +77,8 @@ static mp_obj_t property_setter(mp_obj_t self_in, mp_obj_t setter) { static MP_DEFINE_CONST_FUN_OBJ_2(property_setter_obj, property_setter); static mp_obj_t property_deleter(mp_obj_t self_in, mp_obj_t deleter) { - mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_property_t *p2 = mp_obj_malloc(mp_obj_property_t, &mp_type_property); *p2 = *(mp_obj_property_t *)MP_OBJ_TO_PTR(self_in); p2->proxy[2] = deleter; return MP_OBJ_FROM_PTR(p2); diff --git a/py/objtuple.c b/py/objtuple.c index ec1545abb84ea..42e8d56a806cc 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -86,7 +86,8 @@ static mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg size_t alloc = 4; size_t len = 0; - mp_obj_t *items = m_new(mp_obj_t, alloc); + // CIRCUITPY-CHANGE + mp_obj_t *items = m_malloc_items(alloc); mp_obj_t iterable = mp_getiter(args[0], NULL); mp_obj_t item; diff --git a/py/objtype.c b/py/objtype.c index c2ef10ee9ee54..6def4a4bfd4de 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -96,7 +96,8 @@ static mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *pos_args pos_args++; n_args--; - mp_obj_t *args2 = m_new(mp_obj_t, n_args + 2 * n_kw); + // CIRCUITPY-CHANGE + mp_obj_t *args2 = m_malloc_items(n_args + 2 * n_kw); // copy in args memcpy(args2, pos_args, n_args * sizeof(mp_obj_t)); // copy in kwargs @@ -340,7 +341,8 @@ static mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_arg mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)}; new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2); } else { - mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw); + // CIRCUITPY-CHANGE + mp_obj_t *args2 = m_malloc_items(1 + n_args + 2 * n_kw); args2[0] = MP_OBJ_FROM_PTR(self); memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); new_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2); @@ -371,7 +373,8 @@ static mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_arg if (n_args == 0 && n_kw == 0) { init_ret = mp_call_method_n_kw(0, 0, init_fn); } else { - mp_obj_t *args2 = m_new(mp_obj_t, 2 + n_args + 2 * n_kw); + // CIRCUITPY-CHANGE + mp_obj_t *args2 = m_malloc_items(2 + n_args + 2 * n_kw); args2[0] = init_fn[0]; args2[1] = init_fn[1]; memcpy(args2 + 2, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); @@ -1513,13 +1516,15 @@ mp_obj_t mp_obj_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type /******************************************************************************/ // staticmethod and classmethod types (probably should go in a different file) -static mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { - assert(self == &mp_type_staticmethod || self == &mp_type_classmethod); +// CIRCUITPY-CHANGE: better arg name +static mp_obj_t static_class_method_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + assert(type == &mp_type_staticmethod || type == &mp_type_classmethod); mp_arg_check_num(n_args, n_kw, 1, 1, false); - mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t); - *o = (mp_obj_static_class_method_t) {{self}, args[0]}; + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_static_class_method_t *o = mp_obj_malloc(mp_obj_static_class_method_t, type); + o->fun = args[0]; return MP_OBJ_FROM_PTR(o); } diff --git a/py/qstr.c b/py/qstr.c index 6a5896bdaf4ea..b8bf7360e9271 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -372,10 +372,11 @@ qstr qstr_from_strn(const char *str, size_t len) { if (al < MICROPY_ALLOC_QSTR_CHUNK_INIT) { al = MICROPY_ALLOC_QSTR_CHUNK_INIT; } - MP_STATE_VM(qstr_last_chunk) = m_new_maybe(char, al); + // CIRCUITPY-CHANGE: Don't collect the QSTR blocks that only contain a chunk of a string + MP_STATE_VM(qstr_last_chunk) = m_malloc_maybe_without_collect(sizeof(char) * al); if (MP_STATE_VM(qstr_last_chunk) == NULL) { // failed to allocate a large chunk so try with exact size - MP_STATE_VM(qstr_last_chunk) = m_new_maybe(char, n_bytes); + MP_STATE_VM(qstr_last_chunk) = m_malloc_maybe_without_collect(sizeof(char) * n_bytes); if (MP_STATE_VM(qstr_last_chunk) == NULL) { QSTR_EXIT(); m_malloc_fail(n_bytes); diff --git a/shared-bindings/audiocore/__init__.c b/shared-bindings/audiocore/__init__.c index 5cd1fd83f2297..b2b6c4da0f314 100644 --- a/shared-bindings/audiocore/__init__.c +++ b/shared-bindings/audiocore/__init__.c @@ -39,7 +39,7 @@ static mp_obj_t audiocore_get_buffer(mp_obj_t sample_in) { uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample); audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing); // copies the data because the gc semantics of get_buffer are unclear - void *result_buf = m_malloc(buffer_length); + void *result_buf = m_malloc_without_collect(buffer_length); memcpy(result_buf, buffer, buffer_length); char typecode = (bits_per_sample == 8 && samples_signed) ? 'b' : diff --git a/shared-bindings/displayio/Group.c b/shared-bindings/displayio/Group.c index e5f5f03978975..94ee2e58de15c 100644 --- a/shared-bindings/displayio/Group.c +++ b/shared-bindings/displayio/Group.c @@ -317,12 +317,14 @@ static mp_obj_t group_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t valu //| static mp_obj_t displayio_group_obj_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { displayio_group_t *self = native_group(pos_args[0]); - mp_obj_t *args = m_new(mp_obj_t, n_args); + mp_obj_t *args = m_malloc_items(n_args); for (size_t i = 1; i < n_args; ++i) { args[i] = pos_args[i]; } args[0] = MP_OBJ_FROM_PTR(self->members); - return mp_obj_list_sort(n_args, args, kw_args); + mp_obj_t res = mp_obj_list_sort(n_args, args, kw_args); + m_del(mp_obj_t, args, n_args); + return res; } MP_DEFINE_CONST_FUN_OBJ_KW(displayio_group_sort_obj, 1, displayio_group_obj_sort); diff --git a/shared-bindings/epaperdisplay/EPaperDisplay.c b/shared-bindings/epaperdisplay/EPaperDisplay.c index 0d558a1319616..90828cb1f5a9a 100644 --- a/shared-bindings/epaperdisplay/EPaperDisplay.c +++ b/shared-bindings/epaperdisplay/EPaperDisplay.c @@ -190,7 +190,7 @@ static mp_obj_t epaperdisplay_epaperdisplay_make_new(const mp_obj_type_t *type, size_t refresh_buf_len = 0; mp_int_t refresh_command; if (mp_obj_get_int_maybe(refresh_obj, &refresh_command)) { - uint8_t *command_buf = m_malloc(3); + uint8_t *command_buf = m_malloc_without_collect(3); command_buf[0] = refresh_command; command_buf[1] = 0; command_buf[2] = 0; diff --git a/shared-bindings/synthio/__init__.c b/shared-bindings/synthio/__init__.c index b9252df9fdb61..6d42880541df4 100644 --- a/shared-bindings/synthio/__init__.c +++ b/shared-bindings/synthio/__init__.c @@ -243,7 +243,7 @@ static mp_obj_t synthio_from_file(size_t n_args, const mp_obj_t *pos_args, mp_ma } uint32_t track_size = (chunk_header[4] << 24) | (chunk_header[5] << 16) | (chunk_header[6] << 8) | chunk_header[7]; - uint8_t *buffer = m_malloc(track_size); + uint8_t *buffer = m_malloc_without_collect(track_size); if (f_read(&file->fp, buffer, track_size, &bytes_read) != FR_OK) { mp_raise_OSError(MP_EIO); } diff --git a/shared-module/adafruit_pixelbuf/PixelBuf.c b/shared-module/adafruit_pixelbuf/PixelBuf.c index e62730b3cac3e..155862f17a361 100644 --- a/shared-module/adafruit_pixelbuf/PixelBuf.c +++ b/shared-module/adafruit_pixelbuf/PixelBuf.c @@ -100,7 +100,7 @@ void common_hal_adafruit_pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_f return; } else { if (self->pre_brightness_buffer == NULL) { - self->pre_brightness_buffer = m_malloc(pixel_len); + self->pre_brightness_buffer = m_malloc_without_collect(pixel_len); memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len); } for (size_t i = 0; i < pixel_len; i++) { diff --git a/shared-module/atexit/__init__.c b/shared-module/atexit/__init__.c index 2ed67fd04b792..562b5c3d6b348 100644 --- a/shared-module/atexit/__init__.c +++ b/shared-module/atexit/__init__.c @@ -35,7 +35,7 @@ void shared_module_atexit_register(mp_obj_t *func, size_t n_args, const mp_obj_t .n_pos = 0, .n_kw = 0, .func = func, - .args = (n_args + n_kw_args) ? m_malloc((n_args + (n_kw_args * 2)) * sizeof(mp_obj_t)) : NULL + .args = (n_args + n_kw_args) ? m_malloc_items(n_args + (n_kw_args * 2)) : NULL }; for (; cb.n_pos < n_args; cb.n_pos++) { cb.args[cb.n_pos] = pos_args[cb.n_pos]; diff --git a/shared-module/audiocore/WaveFile.c b/shared-module/audiocore/WaveFile.c index 624541cb1441d..fcad5bc696289 100644 --- a/shared-module/audiocore/WaveFile.c +++ b/shared-module/audiocore/WaveFile.c @@ -119,13 +119,13 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self, self->second_buffer = buffer + self->len; } else { self->len = 256; - self->buffer = m_malloc(self->len); + self->buffer = m_malloc_without_collect(self->len); if (self->buffer == NULL) { common_hal_audioio_wavefile_deinit(self); m_malloc_fail(self->len); } - self->second_buffer = m_malloc(self->len); + self->second_buffer = m_malloc_without_collect(self->len); if (self->second_buffer == NULL) { common_hal_audioio_wavefile_deinit(self); m_malloc_fail(self->len); diff --git a/shared-module/audiodelays/Chorus.c b/shared-module/audiodelays/Chorus.c index 9a8c55fa958e7..1609cc5f94684 100644 --- a/shared-module/audiodelays/Chorus.c +++ b/shared-module/audiodelays/Chorus.c @@ -30,14 +30,14 @@ void common_hal_audiodelays_chorus_construct(audiodelays_chorus_obj_t *self, uin // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... self->buffer_len = buffer_size; // in bytes - self->buffer[0] = m_malloc(self->buffer_len); + self->buffer[0] = m_malloc_without_collect(self->buffer_len); if (self->buffer[0] == NULL) { common_hal_audiodelays_chorus_deinit(self); m_malloc_fail(self->buffer_len); } memset(self->buffer[0], 0, self->buffer_len); - self->buffer[1] = m_malloc(self->buffer_len); + self->buffer[1] = m_malloc_without_collect(self->buffer_len); if (self->buffer[1] == NULL) { common_hal_audiodelays_chorus_deinit(self); m_malloc_fail(self->buffer_len); @@ -78,7 +78,7 @@ void common_hal_audiodelays_chorus_construct(audiodelays_chorus_obj_t *self, uin // Allocate the chorus buffer for the max possible delay, chorus is always 16-bit self->max_delay_ms = max_delay_ms; self->max_chorus_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * max_delay_ms * (self->base.channel_count * sizeof(uint16_t))); // bytes - self->chorus_buffer = m_malloc(self->max_chorus_buffer_len); + self->chorus_buffer = m_malloc_without_collect(self->max_chorus_buffer_len); if (self->chorus_buffer == NULL) { common_hal_audiodelays_chorus_deinit(self); m_malloc_fail(self->max_chorus_buffer_len); diff --git a/shared-module/audiodelays/Echo.c b/shared-module/audiodelays/Echo.c index f4e15b80aa7ef..289d6699506b9 100644 --- a/shared-module/audiodelays/Echo.c +++ b/shared-module/audiodelays/Echo.c @@ -34,14 +34,14 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_ // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... self->buffer_len = buffer_size; // in bytes - self->buffer[0] = m_malloc(self->buffer_len); + self->buffer[0] = m_malloc_without_collect(self->buffer_len); if (self->buffer[0] == NULL) { common_hal_audiodelays_echo_deinit(self); m_malloc_fail(self->buffer_len); } memset(self->buffer[0], 0, self->buffer_len); - self->buffer[1] = m_malloc(self->buffer_len); + self->buffer[1] = m_malloc_without_collect(self->buffer_len); if (self->buffer[1] == NULL) { common_hal_audiodelays_echo_deinit(self); m_malloc_fail(self->buffer_len); @@ -82,7 +82,7 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_ // Allocate the echo buffer for the max possible delay, echo is always 16-bit self->max_delay_ms = max_delay_ms; self->max_echo_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * max_delay_ms) * (self->base.channel_count * sizeof(uint16_t)); // bytes - self->echo_buffer = m_malloc(self->max_echo_buffer_len); + self->echo_buffer = m_malloc_without_collect(self->max_echo_buffer_len); if (self->echo_buffer == NULL) { common_hal_audiodelays_echo_deinit(self); m_malloc_fail(self->max_echo_buffer_len); diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index 743ba403d7961..ac349da0dd50a 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -31,14 +31,14 @@ void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... self->buffer_len = buffer_size; // in bytes - self->buffer[0] = m_malloc(self->buffer_len); + self->buffer[0] = m_malloc_without_collect(self->buffer_len); if (self->buffer[0] == NULL) { common_hal_audiodelays_pitch_shift_deinit(self); m_malloc_fail(self->buffer_len); } memset(self->buffer[0], 0, self->buffer_len); - self->buffer[1] = m_malloc(self->buffer_len); + self->buffer[1] = m_malloc_without_collect(self->buffer_len); if (self->buffer[1] == NULL) { common_hal_audiodelays_pitch_shift_deinit(self); m_malloc_fail(self->buffer_len); @@ -61,7 +61,7 @@ void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t // Allocate the window buffer self->window_len = window; // bytes - self->window_buffer = m_malloc(self->window_len); + self->window_buffer = m_malloc_without_collect(self->window_len); if (self->window_buffer == NULL) { common_hal_audiodelays_pitch_shift_deinit(self); m_malloc_fail(self->window_len); @@ -71,7 +71,7 @@ void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t // Allocate the overlap buffer self->overlap_len = overlap; // bytes if (self->overlap_len) { - self->overlap_buffer = m_malloc(self->overlap_len); + self->overlap_buffer = m_malloc_without_collect(self->overlap_len); if (self->overlap_buffer == NULL) { common_hal_audiodelays_pitch_shift_deinit(self); m_malloc_fail(self->overlap_len); diff --git a/shared-module/audiofilters/Distortion.c b/shared-module/audiofilters/Distortion.c index b1f22c4854528..ec5fe084e56d3 100644 --- a/shared-module/audiofilters/Distortion.c +++ b/shared-module/audiofilters/Distortion.c @@ -40,14 +40,14 @@ void common_hal_audiofilters_distortion_construct(audiofilters_distortion_obj_t // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... self->buffer_len = buffer_size; // in bytes - self->buffer[0] = m_malloc(self->buffer_len); + self->buffer[0] = m_malloc_without_collect(self->buffer_len); if (self->buffer[0] == NULL) { common_hal_audiofilters_distortion_deinit(self); m_malloc_fail(self->buffer_len); } memset(self->buffer[0], 0, self->buffer_len); - self->buffer[1] = m_malloc(self->buffer_len); + self->buffer[1] = m_malloc_without_collect(self->buffer_len); if (self->buffer[1] == NULL) { common_hal_audiofilters_distortion_deinit(self); m_malloc_fail(self->buffer_len); diff --git a/shared-module/audiofilters/Filter.c b/shared-module/audiofilters/Filter.c index c7b0e6bf9646c..19b567532eb8e 100644 --- a/shared-module/audiofilters/Filter.c +++ b/shared-module/audiofilters/Filter.c @@ -31,16 +31,16 @@ void common_hal_audiofilters_filter_construct(audiofilters_filter_obj_t *self, // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... self->buffer_len = buffer_size; // in bytes - self->buffer[0] = m_malloc(self->buffer_len); + self->buffer[0] = m_malloc_without_collect(self->buffer_len); memset(self->buffer[0], 0, self->buffer_len); - self->buffer[1] = m_malloc(self->buffer_len); + self->buffer[1] = m_malloc_without_collect(self->buffer_len); memset(self->buffer[1], 0, self->buffer_len); self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 // This buffer will be used to process samples through the biquad filter - self->filter_buffer = m_malloc(SYNTHIO_MAX_DUR * sizeof(int32_t)); + self->filter_buffer = m_malloc_without_collect(SYNTHIO_MAX_DUR * sizeof(int32_t)); memset(self->filter_buffer, 0, SYNTHIO_MAX_DUR * sizeof(int32_t)); // Initialize other values most effects will need. diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index 775ab41d42f73..2c727a5c0cdde 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -26,13 +26,13 @@ void common_hal_audiomixer_mixer_construct(audiomixer_mixer_obj_t *self, uint32_t sample_rate) { self->len = buffer_size / 2 / sizeof(uint32_t) * sizeof(uint32_t); - self->first_buffer = m_malloc(self->len); + self->first_buffer = m_malloc_without_collect(self->len); if (self->first_buffer == NULL) { common_hal_audiomixer_mixer_deinit(self); m_malloc_fail(self->len); } - self->second_buffer = m_malloc(self->len); + self->second_buffer = m_malloc_without_collect(self->len); if (self->second_buffer == NULL) { common_hal_audiomixer_mixer_deinit(self); m_malloc_fail(self->len); diff --git a/shared-module/audiomp3/MP3Decoder.c b/shared-module/audiomp3/MP3Decoder.c index 3710b8252164d..dc22c0be2454c 100644 --- a/shared-module/audiomp3/MP3Decoder.c +++ b/shared-module/audiomp3/MP3Decoder.c @@ -305,7 +305,7 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t *self, self->inbuf.size = buffer_size - 2 * MAX_BUFFER_LEN; } else { self->inbuf.size = DEFAULT_INPUT_BUFFER_SIZE; - self->inbuf.buf = m_malloc(DEFAULT_INPUT_BUFFER_SIZE); + self->inbuf.buf = m_malloc_without_collect(DEFAULT_INPUT_BUFFER_SIZE); if (self->inbuf.buf == NULL) { common_hal_audiomp3_mp3file_deinit(self); m_malloc_fail(DEFAULT_INPUT_BUFFER_SIZE); @@ -315,13 +315,13 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t *self, self->pcm_buffer[0] = (int16_t *)(void *)buffer; self->pcm_buffer[1] = (int16_t *)(void *)(buffer + MAX_BUFFER_LEN); } else { - self->pcm_buffer[0] = m_malloc(MAX_BUFFER_LEN); + self->pcm_buffer[0] = m_malloc_without_collect(MAX_BUFFER_LEN); if (self->pcm_buffer[0] == NULL) { common_hal_audiomp3_mp3file_deinit(self); m_malloc_fail(MAX_BUFFER_LEN); } - self->pcm_buffer[1] = m_malloc(MAX_BUFFER_LEN); + self->pcm_buffer[1] = m_malloc_without_collect(MAX_BUFFER_LEN); if (self->pcm_buffer[1] == NULL) { common_hal_audiomp3_mp3file_deinit(self); m_malloc_fail(MAX_BUFFER_LEN); diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index d5236f6b4f610..acc41b9eef642 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -31,7 +31,7 @@ void common_hal_displayio_bitmap_construct_from_buffer(displayio_bitmap_t *self, self->stride = stride(width, bits_per_value); self->data_alloc = false; if (!data) { - data = m_malloc(self->stride * height * sizeof(uint32_t)); + data = m_malloc_without_collect(self->stride * height * sizeof(uint32_t)); self->data_alloc = true; } self->data = data; diff --git a/shared-module/displayio/OnDiskBitmap.c b/shared-module/displayio/OnDiskBitmap.c index 9411f08e372c7..9abe8cf4fe1ed 100644 --- a/shared-module/displayio/OnDiskBitmap.c +++ b/shared-module/displayio/OnDiskBitmap.c @@ -114,7 +114,7 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self, uint16_t palette_size = number_of_colors * sizeof(uint32_t); uint16_t palette_offset = 0xe + header_size; - uint32_t *palette_data = m_malloc(palette_size); + uint32_t *palette_data = m_malloc_without_collect(palette_size); f_rewind(&self->file->fp); f_lseek(&self->file->fp, palette_offset); diff --git a/shared-module/displayio/Palette.c b/shared-module/displayio/Palette.c index d80f1c47da171..968296c69f1d0 100644 --- a/shared-module/displayio/Palette.c +++ b/shared-module/displayio/Palette.c @@ -10,7 +10,7 @@ void common_hal_displayio_palette_construct(displayio_palette_t *self, uint16_t color_count, bool dither) { self->color_count = color_count; - self->colors = (_displayio_color_t *)m_malloc(color_count * sizeof(_displayio_color_t)); + self->colors = (_displayio_color_t *)m_malloc_without_collect(color_count * sizeof(_displayio_color_t)); self->dither = dither; } diff --git a/shared-module/displayio/Shape.c b/shared-module/displayio/Shape.c index f36e9e32ac17d..143d37c6c9b35 100644 --- a/shared-module/displayio/Shape.c +++ b/shared-module/displayio/Shape.c @@ -29,7 +29,7 @@ void common_hal_displayio_shape_construct(displayio_shape_t *self, uint32_t widt } self->half_height = height; - self->data = m_malloc(height * sizeof(uint32_t)); + self->data = m_malloc_without_collect(height * sizeof(uint32_t)); for (uint16_t i = 0; i < height; i++) { self->data[2 * i] = 0; diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c index 9312b3e04748b..cfa97130b6aa0 100644 --- a/shared-module/displayio/TileGrid.c +++ b/shared-module/displayio/TileGrid.c @@ -47,13 +47,13 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_ self->inline_tiles = true; } else { if (use_uint16) { - uint16_t *tiles16 = (uint16_t *)m_malloc(total_tiles * sizeof(uint16_t)); + uint16_t *tiles16 = (uint16_t *)m_malloc_without_collect(total_tiles * sizeof(uint16_t)); for (uint32_t i = 0; i < total_tiles; i++) { tiles16[i] = default_tile; } self->tiles = tiles16; } else { - uint8_t *tiles8 = (uint8_t *)m_malloc(total_tiles); + uint8_t *tiles8 = (uint8_t *)m_malloc_without_collect(total_tiles); for (uint32_t i = 0; i < total_tiles; i++) { tiles8[i] = (uint8_t)default_tile; } diff --git a/shared-module/fontio/BuiltinFont.c b/shared-module/fontio/BuiltinFont.c index e24fe9c7f3733..03ef933c55c2f 100644 --- a/shared-module/fontio/BuiltinFont.c +++ b/shared-module/fontio/BuiltinFont.c @@ -16,7 +16,8 @@ mp_obj_t common_hal_fontio_builtinfont_get_bitmap(const fontio_builtinfont_t *se } mp_obj_t common_hal_fontio_builtinfont_get_bounding_box(const fontio_builtinfont_t *self) { - mp_obj_t *items = m_new(mp_obj_t, 2); + // Stack allocation is ok because tuple copies the values out. + mp_obj_t items[2]; items[0] = MP_OBJ_NEW_SMALL_INT(self->width); items[1] = MP_OBJ_NEW_SMALL_INT(self->height); return mp_obj_new_tuple(2, items); diff --git a/shared-module/gifio/GifWriter.c b/shared-module/gifio/GifWriter.c index 8747f4a486ca1..bf0b33836cfd3 100644 --- a/shared-module/gifio/GifWriter.c +++ b/shared-module/gifio/GifWriter.c @@ -70,7 +70,7 @@ void shared_module_gifio_gifwriter_construct(gifio_gifwriter_t *self, mp_obj_t * size_t nblocks = (width * height + 125) / 126; self->size = nblocks * 128 + 4; - self->data = m_malloc(self->size); + self->data = m_malloc_without_collect(self->size); self->cur = 0; self->error = 0; diff --git a/shared-module/keypad/ShiftRegisterKeys.c b/shared-module/keypad/ShiftRegisterKeys.c index f65c9a0532fc5..97917434ff81b 100644 --- a/shared-module/keypad/ShiftRegisterKeys.c +++ b/shared-module/keypad/ShiftRegisterKeys.c @@ -32,9 +32,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_ common_hal_digitalio_digitalinout_switch_to_output(clock, false, DRIVE_MODE_PUSH_PULL); self->clock = clock; - digitalio_digitalinout_obj_t *latch = m_new_obj(digitalio_digitalinout_obj_t); - latch->base.type = &digitalio_digitalinout_type; - + digitalio_digitalinout_obj_t *latch = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(latch, latch_pin); common_hal_digitalio_digitalinout_switch_to_output(latch, true, DRIVE_MODE_PUSH_PULL); self->latch = latch; @@ -42,8 +40,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_ mp_obj_t dios[num_data_pins]; for (size_t i = 0; i < num_data_pins; i++) { - digitalio_digitalinout_obj_t *dio = m_new_obj(digitalio_digitalinout_obj_t); - dio->base.type = &digitalio_digitalinout_type; + digitalio_digitalinout_obj_t *dio = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(dio, data_pins[i]); common_hal_digitalio_digitalinout_switch_to_input(dio, PULL_NONE); dios[i] = dio; @@ -52,7 +49,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_ // Allocate a tuple object with the data pins self->data_pins = mp_obj_new_tuple(num_data_pins, dios); - self->key_counts = (mp_uint_t *)m_malloc(sizeof(mp_uint_t) * num_key_counts); + self->key_counts = (mp_uint_t *)m_malloc_without_collect(sizeof(mp_uint_t) * num_key_counts); self->num_key_counts = num_key_counts; // copy to an m_malloc() and on the fly record pin with largest Shift register diff --git a/shared-module/keypad/__init__.c b/shared-module/keypad/__init__.c index 80e61f3ec7b62..3ffa0433174cf 100644 --- a/shared-module/keypad/__init__.c +++ b/shared-module/keypad/__init__.c @@ -87,7 +87,7 @@ void keypad_deregister_scanner(keypad_scanner_obj_t *scanner) { void keypad_construct_common(keypad_scanner_obj_t *self, mp_float_t interval, size_t max_events, uint8_t debounce_threshold) { size_t key_count = common_hal_keypad_generic_get_key_count(self); - self->debounce_counter = (int8_t *)m_malloc(sizeof(int8_t) * key_count); + self->debounce_counter = (int8_t *)m_malloc_without_collect(sizeof(int8_t) * key_count); self->interval_ticks = (mp_uint_t)(interval * 1024); // interval * 1000 * (1024/1000) diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index 730330175843a..3594c9bb02877 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -71,7 +71,7 @@ const char *common_hal_os_path_abspath(const char *path) { } else { cwd = MP_STATE_VM(cwd_path); if (cwd == NULL) { - char *new_cwd = m_malloc(2); + char *new_cwd = m_malloc_without_collect(2); strcpy(new_cwd, "/"); MP_STATE_VM(cwd_path) = new_cwd; cwd = new_cwd; @@ -79,7 +79,7 @@ const char *common_hal_os_path_abspath(const char *path) { } // Store the current output length for previous components so we can rewind to before them. - char *full_path = m_malloc(strlen(cwd) + strlen(path) + 2); + char *full_path = m_malloc_without_collect(strlen(cwd) + strlen(path) + 2); size_t full_path_len = 0; memcpy(full_path, cwd, strlen(cwd)); full_path_len += strlen(cwd); diff --git a/shared-module/ssl/SSLSocket.c b/shared-module/ssl/SSLSocket.c index 129a48d00d6ee..715d75c3fd5b5 100644 --- a/shared-module/ssl/SSLSocket.c +++ b/shared-module/ssl/SSLSocket.c @@ -65,7 +65,7 @@ static NORETURN void mbedtls_raise_error(int err) { // Try to allocate memory for the message #define ERR_STR_MAX 80 // mbedtls_strerror truncates if it doesn't fit mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); - byte *o_str_buf = m_new_maybe(byte, ERR_STR_MAX); + byte *o_str_buf = m_malloc_without_collect(ERR_STR_MAX); if (o_str == NULL || o_str_buf == NULL) { mp_raise_OSError(err); } diff --git a/shared-module/synthio/__init__.c b/shared-module/synthio/__init__.c index 65fcf2967a1b1..d51ef3dd31019 100644 --- a/shared-module/synthio/__init__.c +++ b/shared-module/synthio/__init__.c @@ -381,8 +381,8 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe synthio_synth_parse_waveform(&synth->waveform_bufinfo, waveform_obj); mp_arg_validate_int_range(channel_count, 1, 2, MP_QSTR_channel_count); synth->buffer_length = SYNTHIO_MAX_DUR * SYNTHIO_BYTES_PER_SAMPLE * channel_count; - synth->buffers[0] = m_malloc(synth->buffer_length); - synth->buffers[1] = m_malloc(synth->buffer_length); + synth->buffers[0] = m_malloc_without_collect(synth->buffer_length); + synth->buffers[1] = m_malloc_without_collect(synth->buffer_length); synth->base.channel_count = channel_count; synth->base.single_buffer = false; synth->other_channel = -1; diff --git a/shared-module/tilepalettemapper/TilePaletteMapper.c b/shared-module/tilepalettemapper/TilePaletteMapper.c index f27c507fdca49..f46810b6a351f 100644 --- a/shared-module/tilepalettemapper/TilePaletteMapper.c +++ b/shared-module/tilepalettemapper/TilePaletteMapper.c @@ -18,9 +18,9 @@ void common_hal_tilepalettemapper_tilepalettemapper_construct(tilepalettemapper_ self->input_color_count = input_color_count; self->needs_refresh = false; int mappings_len = width * height; - self->tile_mappings = (uint32_t **)m_malloc(mappings_len * sizeof(uint32_t *)); + self->tile_mappings = (uint32_t **)m_malloc_without_collect(mappings_len * sizeof(uint32_t *)); for (int i = 0; i < mappings_len; i++) { - self->tile_mappings[i] = (uint32_t *)m_malloc(input_color_count * sizeof(uint32_t)); + self->tile_mappings[i] = (uint32_t *)m_malloc_without_collect(input_color_count * sizeof(uint32_t)); if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) { for (uint16_t j = 0; j < input_color_count; j++) { self->tile_mappings[i][j] = j; diff --git a/shared-module/zlib/__init__.c b/shared-module/zlib/__init__.c index 031432a215fee..7becb6faf73c8 100644 --- a/shared-module/zlib/__init__.c +++ b/shared-module/zlib/__init__.c @@ -37,7 +37,7 @@ mp_obj_t common_hal_zlib_decompress(mp_obj_t data, mp_int_t wbits) { DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp)); uzlib_uncompress_init(decomp, NULL, 0); mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15; - byte *dest_buf = m_new(byte, dest_buf_size); + byte *dest_buf = m_malloc_without_collect(dest_buf_size); decomp->dest = dest_buf; decomp->dest_limit = dest_buf + dest_buf_size;