-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
py/objint: Add mp_obj_int_get_uint_checked() helper. #4928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
py/objint.c
Outdated
@@ -363,6 +363,10 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { | |||
return MP_OBJ_SMALL_INT_VALUE(self_in); | |||
} | |||
|
|||
mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) { | |||
return MP_OBJ_SMALL_INT_VALUE(self_in); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably lean to code reuse here and return mp_obj_int_get_checked so that if the implementation would change you only have to change it once. But I don't know if the compiler is smart enough to skip the extra call, nor if that matters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should trust the compiler to always skip the extra call. I could introduce another helper function/macro to be used by both functions, but I don't think it matters that much.
py/objint_longlong.c
Outdated
@@ -279,6 +279,11 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { | |||
return mp_obj_int_get_truncated(self_in); | |||
} | |||
|
|||
mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) { | |||
// TODO: Check overflow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same remark as above. Bonus: you wouldn't have to repeat this comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same reply, as well :)
I'm not sure that is how it works. The code is there, and part of the public API so it makes it into the binary, no? Maybe since the mp_obj_int_get_uint_checked implementation for mpz is basically the exact same as for signed int except for one function call the implementations can be merged to reduce code size, but it might be somewhat tricky due to the different return values. |
If it's never used it won't make it into the binary, due to linker "garbage collection". |
I was actually thinking in terms of static/shared libraries, my mistake, that's not the standard way MicroPython gets used, so I wonder if that principle also applies there. |
I think there are a few functions which are like this, part of the API but unused by the core (eg |
As @dpgeorge also said, since MicroPython is compiled as a complete executable (and not as a shared library, a part of a bigger executable) and combined with the use of LTO / |
Found another use-case for this function: I can fix it here but it will cause users of @dpgeorge What do you think about this function and the change? |
I made an attempt at it. I don't see any size diff (even when forcing the |
Small incremental size additions could make for a large total.. But I mainly wonder why you think it's better to keep something, if changing it could be beneficial (don't know if it is though, didn't check)? |
In the long run, after there are many users for After all, my intention here is merely to allow future users to choose this API, not to enforce it on current compilations (Which have worked fine and will work fine regardless of this PR) |
py/objint_mpz.c
Outdated
@@ -396,13 +396,13 @@ mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) { | |||
} | |||
} | |||
|
|||
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { | |||
STATIC mp_int_t _mp_obj_int_get_checked(mp_const_obj_t self_in, bool (*as_int)(const mpz_t *i, mp_int_t *value)) { | |||
if (mp_obj_is_small_int(self_in)) { | |||
return MP_OBJ_SMALL_INT_VALUE(self_in); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the intended semantics of mp_obj_int_get_uint_checked()
when the arg is a negative small-int? Since it's "checked" IMO it should raise an exception, since that is what mpz_as_uint_checked()
will do (if the mpz is negative). If you don't want an exception then wouldn't mp_obj_int_get_truncated()
work fine instead of using this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention of using this (in relation to the Linux kernel port) is mainly to catch errors in arithmetic overflow errors before they propagate badly via the kernel FFI. From my personal experience those were usually overflows and not underflows and that's why I think I never encountered this negative small-int problem. That's also why I don't want to use mp_obj_int_get_truncated
.
So yeah, it should raise an exception. I'll fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
py/objint.c
Outdated
@@ -363,6 +363,10 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { | |||
return MP_OBJ_SMALL_INT_VALUE(self_in); | |||
} | |||
|
|||
mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) { | |||
return MP_OBJ_SMALL_INT_VALUE(self_in); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reopening the discussion of #5482 (comment) here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this function.
416b567
to
4d9f787
Compare
I've rebased and fixed the negative small-int case for Regarding What do you think? |
py/objint_mpz.c
Outdated
if (mpz_as_uint_checked(&self->mpz, &value)) { | ||
return value; | ||
} else { | ||
overflow: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid labels and goto (which is nice if possible) this function could be easily restructured so that it falls through to the bottom if there's an overflow, and the mp_raise_msg
is at the bottom. Please try to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are absolutely right. I dunno why I've structured it with a goto
in the first place. I think it's a remnant of having a single function with mp_obj_int_get_checked
.
py/obj.h
Outdated
@@ -748,6 +748,8 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj); | |||
mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in); | |||
// Will raise exception if value doesn't fit into mp_int_t | |||
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); | |||
// Will raise exception if value doesn't fit into mp_uint_t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe write "Will raise exception if value is negative or doesn't fit into mp_uint_t"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair
+1
Let's not bother for now. Can be done in the future if needed. |
Can be used where mp_obj_int_get_checked() will overflow due to the sign-bit solely. This returns an mp_uint_t, so it also verifies the given integer is not negative. Currently implemented only for mpz, since I don't expect this function to be used by ports based on longlong/none impls.
4d9f787
to
27fb52c
Compare
Removed them, and fixed other comments. |
Cool, I didn't know the |
update busio & adafruit_bus_device docs
Can be used where mp_obj_int_get_checked() will overflow due
to the sign-bit solely.
Shouldn't affect code size, since it's unused at the moment.
Should any extmod/port use it, they'd "pay the price".
Addressed #2868, #2269 and possibly more.