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.
diff --git a/py/objint.c b/py/objint.c
index 05269ce..6995416 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -70,15 +70,13 @@
}
}
-#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;
+typedef mp_longint_impl_t fmt_int_t;
#else
-typedef mp_small_int_t fmt_int_t;
+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 @@
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 @@
// 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 @@
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) {