GH-101291: Rearrange the size bits in PyLongObject (GH-102464)

* Eliminate all remaining uses of Py_SIZE and Py_SET_SIZE on PyLongObject, adding asserts.

* Change layout of size/sign bits in longobject to support future addition of immortal ints and tagged medium ints.

* Add functions to hide some internals of long object, and for setting sign and digit count.

* Replace uses of IS_MEDIUM_VALUE macro with _PyLong_IsCompact().
This commit is contained in:
Mark Shannon 2023-03-22 14:49:51 +00:00 committed by GitHub
parent 713df2c534
commit 7559f5fda9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 982 additions and 898 deletions

View file

@ -11,6 +11,7 @@
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_code.h" // _PyCode_New()
#include "pycore_long.h" // _PyLong_DigitCount
#include "pycore_hashtable.h" // _Py_hashtable_t
#include "marshal.h" // Py_MARSHAL_VERSION
@ -232,13 +233,13 @@ w_PyLong(const PyLongObject *ob, char flag, WFILE *p)
digit d;
W_TYPE(TYPE_LONG, p);
if (Py_SIZE(ob) == 0) {
if (_PyLong_IsZero(ob)) {
w_long((long)0, p);
return;
}
/* set l to number of base PyLong_MARSHAL_BASE digits */
n = Py_ABS(Py_SIZE(ob));
n = _PyLong_DigitCount(ob);
l = (n-1) * PyLong_MARSHAL_RATIO;
d = ob->long_value.ob_digit[n-1];
assert(d != 0); /* a PyLong is always normalized */
@ -251,7 +252,7 @@ w_PyLong(const PyLongObject *ob, char flag, WFILE *p)
p->error = WFERR_UNMARSHALLABLE;
return;
}
w_long((long)(Py_SIZE(ob) > 0 ? l : -l), p);
w_long((long)(_PyLong_IsNegative(ob) ? -l : l), p);
for (i=0; i < n-1; i++) {
d = ob->long_value.ob_digit[i];
@ -839,7 +840,7 @@ r_PyLong(RFILE *p)
if (ob == NULL)
return NULL;
Py_SET_SIZE(ob, n > 0 ? size : -size);
_PyLong_SetSignAndDigitCount(ob, n < 0 ? -1 : 1, size);
for (i = 0; i < size-1; i++) {
d = 0;