bpo-42161: Add _PyLong_GetZero() and _PyLong_GetOne() (GH-22993)
Add _PyLong_GetZero() and _PyLong_GetOne() functions and a new internal pycore_long.h header file. Python cannot be built without small integer singletons anymore.
This commit is contained in:
parent
bca7014032
commit
8e3b9f9283
|
@ -163,6 +163,11 @@ struct _Py_exc_state {
|
||||||
#define _PY_NSMALLPOSINTS 257
|
#define _PY_NSMALLPOSINTS 257
|
||||||
#define _PY_NSMALLNEGINTS 5
|
#define _PY_NSMALLNEGINTS 5
|
||||||
|
|
||||||
|
// _PyLong_GetZero() and _PyLong_GetOne() must always be available
|
||||||
|
#if _PY_NSMALLPOSINTS < 2
|
||||||
|
# error "_PY_NSMALLPOSINTS must be greater than 1"
|
||||||
|
#endif
|
||||||
|
|
||||||
// The PyInterpreterState typedef is in Include/pystate.h.
|
// The PyInterpreterState typedef is in Include/pystate.h.
|
||||||
struct _is {
|
struct _is {
|
||||||
|
|
||||||
|
@ -233,14 +238,12 @@ struct _is {
|
||||||
|
|
||||||
PyObject *audit_hooks;
|
PyObject *audit_hooks;
|
||||||
|
|
||||||
#if _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS > 0
|
|
||||||
/* Small integers are preallocated in this array so that they
|
/* Small integers are preallocated in this array so that they
|
||||||
can be shared.
|
can be shared.
|
||||||
The integers that are preallocated are those in the range
|
The integers that are preallocated are those in the range
|
||||||
-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive).
|
-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive).
|
||||||
*/
|
*/
|
||||||
PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
|
PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
|
||||||
#endif
|
|
||||||
struct _Py_bytes_state bytes;
|
struct _Py_bytes_state bytes;
|
||||||
struct _Py_unicode_state unicode;
|
struct _Py_unicode_state unicode;
|
||||||
struct _Py_float_state float_state;
|
struct _Py_float_state float_state;
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef Py_INTERNAL_LONG_H
|
||||||
|
#define Py_INTERNAL_LONG_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Py_BUILD_CORE
|
||||||
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_interp.h" // PyInterpreterState.small_ints
|
||||||
|
#include "pycore_pystate.h" // _PyThreadState_GET()
|
||||||
|
|
||||||
|
// Don't call this function but _PyLong_GetZero() and _PyLong_GetOne()
|
||||||
|
static inline PyObject* __PyLong_GetSmallInt_internal(int value)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
_Py_EnsureTstateNotNULL(tstate);
|
||||||
|
#endif
|
||||||
|
assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS);
|
||||||
|
size_t index = _PY_NSMALLNEGINTS + value;
|
||||||
|
PyObject *obj = (PyObject*)tstate->interp->small_ints[index];
|
||||||
|
// _PyLong_GetZero() and _PyLong_GetOne() must not be called
|
||||||
|
// before _PyLong_Init() nor after _PyLong_Fini()
|
||||||
|
assert(obj != NULL);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a borrowed reference to the zero singleton.
|
||||||
|
// The function cannot return NULL.
|
||||||
|
static inline PyObject* _PyLong_GetZero(void)
|
||||||
|
{ return __PyLong_GetSmallInt_internal(0); }
|
||||||
|
|
||||||
|
// Return a borrowed reference to the one singleton.
|
||||||
|
// The function cannot return NULL.
|
||||||
|
static inline PyObject* _PyLong_GetOne(void)
|
||||||
|
{ return __PyLong_GetSmallInt_internal(1); }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* !Py_INTERNAL_LONG_H */
|
|
@ -1117,6 +1117,7 @@ PYTHON_HEADERS= \
|
||||||
$(srcdir)/Include/internal/pycore_initconfig.h \
|
$(srcdir)/Include/internal/pycore_initconfig.h \
|
||||||
$(srcdir)/Include/internal/pycore_interp.h \
|
$(srcdir)/Include/internal/pycore_interp.h \
|
||||||
$(srcdir)/Include/internal/pycore_list.h \
|
$(srcdir)/Include/internal/pycore_list.h \
|
||||||
|
$(srcdir)/Include/internal/pycore_long.h \
|
||||||
$(srcdir)/Include/internal/pycore_object.h \
|
$(srcdir)/Include/internal/pycore_object.h \
|
||||||
$(srcdir)/Include/internal/pycore_pathconfig.h \
|
$(srcdir)/Include/internal/pycore_pathconfig.h \
|
||||||
$(srcdir)/Include/internal/pycore_pyerrors.h \
|
$(srcdir)/Include/internal/pycore_pyerrors.h \
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_bitutils.h" // _Py_popcount32()
|
#include "pycore_bitutils.h" // _Py_popcount32()
|
||||||
#include "pycore_interp.h" // _PY_NSMALLPOSINTS
|
#include "pycore_interp.h" // _PY_NSMALLPOSINTS
|
||||||
|
#include "pycore_long.h" // __PyLong_GetSmallInt_internal()
|
||||||
#include "pycore_object.h" // _PyObject_InitVar()
|
#include "pycore_object.h" // _PyObject_InitVar()
|
||||||
#include "pycore_pystate.h" // _Py_IsMainInterpreter()
|
#include "pycore_pystate.h" // _Py_IsMainInterpreter()
|
||||||
#include "longintrepr.h"
|
#include "longintrepr.h"
|
||||||
|
@ -19,8 +20,8 @@ class int "PyObject *" "&PyLong_Type"
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ec0275e3422a36e3]*/
|
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ec0275e3422a36e3]*/
|
||||||
|
|
||||||
#define NSMALLPOSINTS _PY_NSMALLPOSINTS
|
|
||||||
#define NSMALLNEGINTS _PY_NSMALLNEGINTS
|
#define NSMALLNEGINTS _PY_NSMALLNEGINTS
|
||||||
|
#define NSMALLPOSINTS _PY_NSMALLPOSINTS
|
||||||
|
|
||||||
_Py_IDENTIFIER(little);
|
_Py_IDENTIFIER(little);
|
||||||
_Py_IDENTIFIER(big);
|
_Py_IDENTIFIER(big);
|
||||||
|
@ -34,7 +35,6 @@ _Py_IDENTIFIER(big);
|
||||||
PyObject *_PyLong_Zero = NULL;
|
PyObject *_PyLong_Zero = NULL;
|
||||||
PyObject *_PyLong_One = NULL;
|
PyObject *_PyLong_One = NULL;
|
||||||
|
|
||||||
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
|
||||||
#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
|
#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
|
||||||
#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
|
#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
|
||||||
|
|
||||||
|
@ -42,8 +42,7 @@ static PyObject *
|
||||||
get_small_int(sdigit ival)
|
get_small_int(sdigit ival)
|
||||||
{
|
{
|
||||||
assert(IS_SMALL_INT(ival));
|
assert(IS_SMALL_INT(ival));
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyObject *v = __PyLong_GetSmallInt_internal(ival);
|
||||||
PyObject *v = (PyObject*)interp->small_ints[ival + NSMALLNEGINTS];
|
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -60,12 +59,6 @@ maybe_small_long(PyLongObject *v)
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define IS_SMALL_INT(ival) 0
|
|
||||||
#define IS_SMALL_UINT(ival) 0
|
|
||||||
#define get_small_int(ival) (Py_UNREACHABLE(), NULL)
|
|
||||||
#define maybe_small_long(val) (val)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If a freshly-allocated int is already shared, it must
|
/* If a freshly-allocated int is already shared, it must
|
||||||
be a small integer, so negating it must go to PyLong_FromLong */
|
be a small integer, so negating it must go to PyLong_FromLong */
|
||||||
|
@ -2559,8 +2552,9 @@ long_divrem(PyLongObject *a, PyLongObject *b,
|
||||||
if (*prem == NULL) {
|
if (*prem == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
Py_INCREF(_PyLong_Zero);
|
PyObject *zero = _PyLong_GetZero();
|
||||||
*pdiv = (PyLongObject*)_PyLong_Zero;
|
Py_INCREF(zero);
|
||||||
|
*pdiv = (PyLongObject*)zero;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (size_b == 1) {
|
if (size_b == 1) {
|
||||||
|
@ -3669,7 +3663,7 @@ l_divmod(PyLongObject *v, PyLongObject *w,
|
||||||
Py_DECREF(div);
|
Py_DECREF(div);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
temp = (PyLongObject *) long_sub(div, (PyLongObject *)_PyLong_One);
|
temp = (PyLongObject *) long_sub(div, (PyLongObject *)_PyLong_GetOne());
|
||||||
if (temp == NULL) {
|
if (temp == NULL) {
|
||||||
Py_DECREF(mod);
|
Py_DECREF(mod);
|
||||||
Py_DECREF(div);
|
Py_DECREF(div);
|
||||||
|
@ -4078,7 +4072,7 @@ long_invmod(PyLongObject *a, PyLongObject *n)
|
||||||
|
|
||||||
Py_DECREF(c);
|
Py_DECREF(c);
|
||||||
Py_DECREF(n);
|
Py_DECREF(n);
|
||||||
if (long_compare(a, (PyLongObject *)_PyLong_One)) {
|
if (long_compare(a, (PyLongObject *)_PyLong_GetOne())) {
|
||||||
/* a != 1; we don't have an inverse. */
|
/* a != 1; we don't have an inverse. */
|
||||||
Py_DECREF(a);
|
Py_DECREF(a);
|
||||||
Py_DECREF(b);
|
Py_DECREF(b);
|
||||||
|
@ -4313,7 +4307,7 @@ long_invert(PyLongObject *v)
|
||||||
PyLongObject *x;
|
PyLongObject *x;
|
||||||
if (Py_ABS(Py_SIZE(v)) <=1)
|
if (Py_ABS(Py_SIZE(v)) <=1)
|
||||||
return PyLong_FromLong(-(MEDIUM_VALUE(v)+1));
|
return PyLong_FromLong(-(MEDIUM_VALUE(v)+1));
|
||||||
x = (PyLongObject *) long_add(v, (PyLongObject *)_PyLong_One);
|
x = (PyLongObject *) long_add(v, (PyLongObject *)_PyLong_GetOne());
|
||||||
if (x == NULL)
|
if (x == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
_PyLong_Negate(&x);
|
_PyLong_Negate(&x);
|
||||||
|
@ -5105,7 +5099,8 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b)
|
||||||
|
|
||||||
/* compare twice the remainder with the divisor, to see
|
/* compare twice the remainder with the divisor, to see
|
||||||
if we need to adjust the quotient and remainder */
|
if we need to adjust the quotient and remainder */
|
||||||
twice_rem = long_lshift((PyObject *)rem, _PyLong_One);
|
PyObject *one = _PyLong_GetOne(); // borrowed reference
|
||||||
|
twice_rem = long_lshift((PyObject *)rem, one);
|
||||||
if (twice_rem == NULL)
|
if (twice_rem == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
if (quo_is_neg) {
|
if (quo_is_neg) {
|
||||||
|
@ -5122,9 +5117,9 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b)
|
||||||
if ((Py_SIZE(b) < 0 ? cmp < 0 : cmp > 0) || (cmp == 0 && quo_is_odd)) {
|
if ((Py_SIZE(b) < 0 ? cmp < 0 : cmp > 0) || (cmp == 0 && quo_is_odd)) {
|
||||||
/* fix up quotient */
|
/* fix up quotient */
|
||||||
if (quo_is_neg)
|
if (quo_is_neg)
|
||||||
temp = long_sub(quo, (PyLongObject *)_PyLong_One);
|
temp = long_sub(quo, (PyLongObject *)one);
|
||||||
else
|
else
|
||||||
temp = long_add(quo, (PyLongObject *)_PyLong_One);
|
temp = long_add(quo, (PyLongObject *)one);
|
||||||
Py_DECREF(quo);
|
Py_DECREF(quo);
|
||||||
quo = (PyLongObject *)temp;
|
quo = (PyLongObject *)temp;
|
||||||
if (quo == NULL)
|
if (quo == NULL)
|
||||||
|
@ -5406,7 +5401,7 @@ int_as_integer_ratio_impl(PyObject *self)
|
||||||
if (numerator == NULL) {
|
if (numerator == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ratio_tuple = PyTuple_Pack(2, numerator, _PyLong_One);
|
ratio_tuple = PyTuple_Pack(2, numerator, _PyLong_GetOne());
|
||||||
Py_DECREF(numerator);
|
Py_DECREF(numerator);
|
||||||
return ratio_tuple;
|
return ratio_tuple;
|
||||||
}
|
}
|
||||||
|
@ -5712,7 +5707,6 @@ PyLong_GetInfo(void)
|
||||||
int
|
int
|
||||||
_PyLong_Init(PyThreadState *tstate)
|
_PyLong_Init(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
|
||||||
for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
|
for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
|
||||||
sdigit ival = (sdigit)i - NSMALLNEGINTS;
|
sdigit ival = (sdigit)i - NSMALLNEGINTS;
|
||||||
int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
|
int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
|
||||||
|
@ -5727,7 +5721,6 @@ _PyLong_Init(PyThreadState *tstate)
|
||||||
|
|
||||||
tstate->interp->small_ints[i] = v;
|
tstate->interp->small_ints[i] = v;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (_Py_IsMainInterpreter(tstate)) {
|
if (_Py_IsMainInterpreter(tstate)) {
|
||||||
_PyLong_Zero = PyLong_FromLong(0);
|
_PyLong_Zero = PyLong_FromLong(0);
|
||||||
|
@ -5759,9 +5752,7 @@ _PyLong_Fini(PyThreadState *tstate)
|
||||||
Py_CLEAR(_PyLong_Zero);
|
Py_CLEAR(_PyLong_Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
|
||||||
for (Py_ssize_t i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
|
for (Py_ssize_t i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
|
||||||
Py_CLEAR(tstate->interp->small_ints[i]);
|
Py_CLEAR(tstate->interp->small_ints[i]);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,6 +185,7 @@
|
||||||
<ClInclude Include="..\Include\internal\pycore_initconfig.h" />
|
<ClInclude Include="..\Include\internal\pycore_initconfig.h" />
|
||||||
<ClInclude Include="..\Include\internal\pycore_interp.h" />
|
<ClInclude Include="..\Include\internal\pycore_interp.h" />
|
||||||
<ClInclude Include="..\Include\internal\pycore_list.h" />
|
<ClInclude Include="..\Include\internal\pycore_list.h" />
|
||||||
|
<ClInclude Include="..\Include\internal\pycore_long.h" />
|
||||||
<ClInclude Include="..\Include\internal\pycore_object.h" />
|
<ClInclude Include="..\Include\internal\pycore_object.h" />
|
||||||
<ClInclude Include="..\Include\internal\pycore_pathconfig.h" />
|
<ClInclude Include="..\Include\internal\pycore_pathconfig.h" />
|
||||||
<ClInclude Include="..\Include\internal\pycore_pyerrors.h" />
|
<ClInclude Include="..\Include\internal\pycore_pyerrors.h" />
|
||||||
|
|
|
@ -537,6 +537,9 @@
|
||||||
<ClInclude Include="..\Include\internal\pycore_list.h">
|
<ClInclude Include="..\Include\internal\pycore_list.h">
|
||||||
<Filter>Include\internal</Filter>
|
<Filter>Include\internal</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\Include\internal\pycore_long.h">
|
||||||
|
<Filter>Include\internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\Include\internal\pycore_object.h">
|
<ClInclude Include="..\Include\internal\pycore_object.h">
|
||||||
<Filter>Include\internal</Filter>
|
<Filter>Include\internal</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
Loading…
Reference in New Issue