py: Make it so that printing a small int does not allocate heap memory.
With the implementation of proper string formatting, code to print a small int was delegated to mpz_as_str_inpl (after first converting the small int to an mpz using stack memory). But mpz_as_str_inpl allocates heap memory to do the conversion, so small ints needed heap memory just to be printed. This fix has a separate function to print small ints, which does not allocate heap, and allocates less stack. String formatting, printf and pfenv are now large beasts, with some semi-duplicated code.
This commit is contained in:
parent
803b9263ab
commit
88d7bba961
42
py/objint.c
42
py/objint.c
@ -70,15 +70,13 @@ void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env,
|
||||
}
|
||||
}
|
||||
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE || MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
|
||||
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
|
||||
typedef mp_longint_impl_t fmt_int_t;
|
||||
#else
|
||||
typedef mp_small_int_t fmt_int_t;
|
||||
#endif
|
||||
|
||||
static const uint log_base2_floor[] = {
|
||||
STATIC const uint log_base2_floor[] = {
|
||||
0,
|
||||
0, 1, 1, 2,
|
||||
2, 2, 2, 3,
|
||||
@ -90,7 +88,7 @@ static const uint log_base2_floor[] = {
|
||||
4, 4, 4, 5
|
||||
};
|
||||
|
||||
uint int_as_str_size_formatted(uint base, const char *prefix, char comma) {
|
||||
STATIC uint int_as_str_size_formatted(uint base, const char *prefix, char comma) {
|
||||
if (base < 2 || base > 32) {
|
||||
return 0;
|
||||
}
|
||||
@ -110,22 +108,29 @@ uint int_as_str_size_formatted(uint base, const char *prefix, char comma) {
|
||||
// formatted size will be in *fmt_size.
|
||||
char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in,
|
||||
int base, const char *prefix, char base_char, char comma) {
|
||||
if (!MP_OBJ_IS_INT(self_in)) {
|
||||
fmt_int_t num;
|
||||
if (MP_OBJ_IS_SMALL_INT(self_in)) {
|
||||
// A small int; get the integer value to format.
|
||||
num = mp_obj_get_int(self_in);
|
||||
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
|
||||
} else if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
|
||||
// Not a small int.
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
|
||||
mp_obj_int_t *self = self_in;
|
||||
// Get the value to format; mp_obj_get_int truncates to machine_int_t.
|
||||
num = self->val;
|
||||
#else
|
||||
// Delegate to the implementation for the long int.
|
||||
return mp_obj_int_formatted_impl(buf, buf_size, fmt_size, self_in, base, prefix, base_char, comma);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
// Not an int.
|
||||
buf[0] = '\0';
|
||||
*fmt_size = 0;
|
||||
return *buf;
|
||||
}
|
||||
fmt_int_t num;
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
|
||||
mp_obj_int_t *self = self_in;
|
||||
if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
|
||||
// mp_obj_get_int truncates to machine_int_t
|
||||
num = self->val;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
num = mp_obj_get_int(self_in);
|
||||
}
|
||||
|
||||
char sign = '\0';
|
||||
if (num < 0) {
|
||||
num = -num;
|
||||
@ -180,12 +185,11 @@ char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_obj_t se
|
||||
return b;
|
||||
}
|
||||
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
|
||||
|
||||
bool mp_obj_int_is_positive(mp_obj_t self_in) {
|
||||
return mp_obj_get_int(self_in) >= 0;
|
||||
}
|
||||
#endif // LONGLONG or NONE
|
||||
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
|
||||
|
||||
// This is called for operations on SMALL_INT that are not handled by mp_unary_op
|
||||
mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in) {
|
||||
|
@ -10,6 +10,8 @@ typedef struct _mp_obj_int_t {
|
||||
void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in,
|
||||
int base, const char *prefix, char base_char, char comma);
|
||||
char *mp_obj_int_formatted_impl(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in,
|
||||
int base, const char *prefix, char base_char, char comma);
|
||||
bool mp_obj_int_is_positive(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in);
|
||||
mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in);
|
||||
|
@ -22,6 +22,14 @@
|
||||
#define SUFFIX ""
|
||||
#endif
|
||||
|
||||
bool mp_obj_int_is_positive(mp_obj_t self_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(self_in)) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(self_in) >= 0;
|
||||
}
|
||||
mp_obj_int_t *self = self_in;
|
||||
return self->val >= 0;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in) {
|
||||
mp_obj_int_t *o = o_in;
|
||||
switch (op) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
@ -29,30 +30,21 @@ STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) {
|
||||
//
|
||||
// The resulting formatted string will be returned from this function and the
|
||||
// formatted size will be in *fmt_size.
|
||||
char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in,
|
||||
//
|
||||
// This particular routine should only be called for the mpz representation of the int.
|
||||
char *mp_obj_int_formatted_impl(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in,
|
||||
int base, const char *prefix, char base_char, char comma) {
|
||||
mpz_t small_mpz;
|
||||
mpz_t *mpz;
|
||||
mpz_dig_t small_dig[(sizeof(mp_small_int_t) * 8 + MPZ_DIG_SIZE - 1) / MPZ_DIG_SIZE];
|
||||
|
||||
if (MP_OBJ_IS_SMALL_INT(self_in)) {
|
||||
mpz_init_fixed_from_int(&small_mpz, small_dig,
|
||||
sizeof(small_dig) / sizeof(small_dig[0]),
|
||||
MP_OBJ_SMALL_INT_VALUE(self_in));
|
||||
mpz = &small_mpz;
|
||||
} else {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
|
||||
mp_obj_int_t *self = self_in;
|
||||
mpz = &self->mpz;
|
||||
}
|
||||
|
||||
uint needed_size = mpz_as_str_size_formatted(mpz, base, prefix, comma);
|
||||
uint needed_size = mpz_as_str_size_formatted(&self->mpz, base, prefix, comma);
|
||||
if (needed_size > *buf_size) {
|
||||
*buf = m_new(char, needed_size);
|
||||
*buf_size = needed_size;
|
||||
}
|
||||
char *str = *buf;
|
||||
|
||||
*fmt_size = mpz_as_str_inpl(mpz, base, prefix, base_char, comma, str);
|
||||
*fmt_size = mpz_as_str_inpl(&self->mpz, base, prefix, base_char, comma, str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user