summaryrefslogtreecommitdiff
path: root/ports/unix/coverage.c
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2022-10-06 13:44:54 +1100
committerDamien George <damien@micropython.org>2024-07-01 13:52:59 +1000
commit557d31ed2c75e90b2f2c534c7019cb51aab5a7c8 (patch)
tree1a76c8cbbc1863a167d4f52bfbe73cc34f487191 /ports/unix/coverage.c
parent0600e4f27333092884358c967123dcc040d7a1cc (diff)
py/objint: Try to convert big-int back to small-int after binary op.
Before this change, long/mpz ints propagated into all future calculations, even if their value could fit in a small-int object. With this change, the result of a big-int binary op will now be converted to a small-int object if the value fits in a small-int. For example, a relatively common operation like `x = a * b // c` where a,b,c all small ints would always result in a long/mpz int, even if it didn't need to, and then this would impact all future calculations with x. This adds +24 bytes on PYBV11 but avoids heap allocations and potential surprises (e.g. `big-big` is now a small `0`, and can safely be accessed with MP_OBJ_SMALL_INT_VALUE). Performance tests are unchanged on PYBV10, except for `bm_pidigits.py` which makes heavy use of big-ints and gains about 8% in speed. Unix coverage tests have been updated to cover mpz code that is now unreachable by normal Python code (removing the unreachable code would lead to some surprising gaps in the internal C functions and the functionality may be needed in the future, so it is kept because it has minimal overhead). This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Diffstat (limited to 'ports/unix/coverage.c')
-rw-r--r--ports/unix/coverage.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c
index 803f84953..b05e2dade 100644
--- a/ports/unix/coverage.c
+++ b/ports/unix/coverage.c
@@ -4,6 +4,7 @@
#include "py/obj.h"
#include "py/objfun.h"
+#include "py/objint.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/gc.h"
@@ -454,6 +455,13 @@ static mp_obj_t extra_coverage(void) {
mpz_mul_inpl(&mpz, &mpz2, &mpz);
mpz_as_uint_checked(&mpz, &value);
mp_printf(&mp_plat_print, "%d\n", (int)value);
+
+ // mpz_not_inpl with argument==0, testing ~0
+ mpz_set_from_int(&mpz, 0);
+ mpz_not_inpl(&mpz, &mpz);
+ mp_int_t value_signed;
+ mpz_as_int_checked(&mpz, &value_signed);
+ mp_printf(&mp_plat_print, "%d\n", (int)value_signed);
}
// runtime utils
@@ -470,6 +478,9 @@ static mp_obj_t extra_coverage(void) {
// call mp_call_function_2_protected with invalid args
mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), mp_obj_new_str("abc", 3), mp_obj_new_str("abc", 3));
+ // mp_obj_int_get_checked with mp_obj_int_t that has a value that is a small integer
+ mp_printf(&mp_plat_print, "%d\n", mp_obj_int_get_checked(mp_obj_int_new_mpz()));
+
// mp_obj_int_get_uint_checked with non-negative small-int
mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(1)));