core: Add MP_BUFFER_GET_BASE

This flag requests that the filled bufinfo give the associated
GC base address, for classes like memoryview & uctypes that need
it in order to ensure liveness of the data they refer to.

I had initially hoped that this would be a forward compatible
change, but the practice of checking `flags == MP_BUFFER_READ`
means it's not, so I might as well make it unconditional. But,
here, it's an intermediate step that passed the tests.
This commit is contained in:
Jeff Epler 2025-07-20 13:30:02 -05:00
parent a06e973ddc
commit 6d16c8d3fe
9 changed files with 18 additions and 7 deletions

View file

@ -82,7 +82,7 @@ mp_obj_t mp_vfs_rom_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_
static mp_int_t vfs_rom_file_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
mp_obj_vfs_rom_file_t *self = MP_OBJ_TO_PTR(self_in);
if (flags == MP_BUFFER_READ) {
if ((flags & MP_BUFFER_RW) == MP_BUFFER_READ) {
bufinfo->buf = (void *)self->file_data;
bufinfo->len = self->file_size;
bufinfo->typecode = 'B';

View file

@ -82,7 +82,7 @@ static mp_obj_t alif_flash_make_new(const mp_obj_type_t *type, size_t n_args, si
static mp_int_t alif_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
alif_flash_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (flags == MP_BUFFER_READ) {
if ((flags & MP_BUFFER_RW) == MP_BUFFER_READ) {
bufinfo->buf = (void *)(ospi_flash_get_xip_base() + self->flash_base_addr);
bufinfo->len = self->flash_size;
bufinfo->typecode = 'B';

View file

@ -131,7 +131,7 @@ static mp_obj_t esp32_partition_make_new(const mp_obj_type_t *type, size_t n_arg
#if MICROPY_VFS_ROM_IOCTL
static mp_int_t esp32_partition_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self == &esp32_partition_romfs_obj && flags == MP_BUFFER_READ) {
if (self == &esp32_partition_romfs_obj && (flags & MP_BUFFER_RW) == MP_BUFFER_READ) {
if (esp32_partition_romfs_ptr == NULL) {
check_esp_err(esp_partition_mmap(self->part, 0, self->part->size, ESP_PARTITION_MMAP_DATA, &esp32_partition_romfs_ptr, &esp32_partition_romfs_handle));
}

View file

@ -232,7 +232,7 @@ static mp_obj_t rp2_flash_make_new(const mp_obj_type_t *type, size_t n_args, siz
static mp_int_t rp2_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
rp2_flash_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (flags == MP_BUFFER_READ) {
if ((flags & MP_BUFFER_RW) == MP_BUFFER_READ) {
bufinfo->buf = (void *)(XIP_BASE + self->flash_base);
bufinfo->len = self->flash_size;
bufinfo->typecode = 'B';

View file

@ -586,8 +586,14 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
const mp_obj_type_t *type = mp_obj_get_type(obj);
if (flags & MP_BUFFER_GET_BASE) {
bufinfo->base = NULL;
}
if (MP_OBJ_TYPE_HAS_SLOT(type, buffer)
&& MP_OBJ_TYPE_GET_SLOT(type, buffer)(obj, bufinfo, flags & MP_BUFFER_RW) == 0) {
&& MP_OBJ_TYPE_GET_SLOT(type, buffer)(obj, bufinfo, flags & ~MP_BUFFER_RAISE_IF_UNSUPPORTED) == 0) {
if ((flags & MP_BUFFER_GET_BASE) && !bufinfo->base) {
bufinfo->base = bufinfo->buf;
}
return true;
}
if (flags & MP_BUFFER_RAISE_IF_UNSUPPORTED) {

View file

@ -608,12 +608,14 @@ typedef struct _mp_buffer_info_t {
void *buf; // can be NULL if len == 0
size_t len; // in bytes
int typecode; // as per binary.h
void *base; // the "base address" of the buffer, only populated if MP_BUFFER_GET_BASE flag is set and the type supports it.
} mp_buffer_info_t;
#define MP_BUFFER_READ (1)
#define MP_BUFFER_WRITE (2)
#define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE)
#define MP_BUFFER_RAISE_IF_UNSUPPORTED (4)
#define MP_BUFFER_GET_BASE (8) // populate the "base" pointer
typedef mp_int_t (*mp_buffer_fun_t)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags);

View file

@ -599,6 +599,9 @@ static mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui
return 1;
}
bufinfo->buf = (uint8_t *)bufinfo->buf + (size_t)o->memview_offset * sz;
if (flags & MP_BUFFER_GET_BASE) {
bufinfo->base = (uint8_t *)o->items;
}
}
#else
(void)flags;

View file

@ -40,7 +40,7 @@ typedef struct _micropython_ringio_obj_t {
static mp_obj_t micropython_ringio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 1, false);
mp_int_t buff_size = -1;
mp_buffer_info_t bufinfo = {NULL, 0, 0};
mp_buffer_info_t bufinfo = {NULL, 0, 0, 0};
if (!mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
buff_size = mp_obj_get_int(args[0]);

View file

@ -2060,7 +2060,7 @@ static MP_DEFINE_CONST_CLASSMETHOD_OBJ(bytes_fromhex_classmethod_obj, MP_ROM_PTR
#endif // MICROPY_PY_BUILTINS_BYTES_HEX
mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
if (flags == MP_BUFFER_READ) {
if ((flags & MP_BUFFER_RW) == MP_BUFFER_READ) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
bufinfo->buf = (void *)str_data;
bufinfo->len = str_len;