Skip to content

Commit 8e3b9f9

Browse files
authored
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.
1 parent bca7014 commit 8e3b9f9

File tree

6 files changed

+67
-25
lines changed

6 files changed

+67
-25
lines changed

Include/internal/pycore_interp.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ struct _Py_exc_state {
163163
#define _PY_NSMALLPOSINTS 257
164164
#define _PY_NSMALLNEGINTS 5
165165

166+
// _PyLong_GetZero() and _PyLong_GetOne() must always be available
167+
#if _PY_NSMALLPOSINTS < 2
168+
# error "_PY_NSMALLPOSINTS must be greater than 1"
169+
#endif
170+
166171
// The PyInterpreterState typedef is in Include/pystate.h.
167172
struct _is {
168173

@@ -233,14 +238,12 @@ struct _is {
233238

234239
PyObject *audit_hooks;
235240

236-
#if _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS > 0
237241
/* Small integers are preallocated in this array so that they
238242
can be shared.
239243
The integers that are preallocated are those in the range
240244
-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive).
241245
*/
242246
PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
243-
#endif
244247
struct _Py_bytes_state bytes;
245248
struct _Py_unicode_state unicode;
246249
struct _Py_float_state float_state;

Include/internal/pycore_long.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#ifndef Py_INTERNAL_LONG_H
2+
#define Py_INTERNAL_LONG_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
#ifndef Py_BUILD_CORE
8+
# error "this header requires Py_BUILD_CORE define"
9+
#endif
10+
11+
#include "pycore_interp.h" // PyInterpreterState.small_ints
12+
#include "pycore_pystate.h" // _PyThreadState_GET()
13+
14+
// Don't call this function but _PyLong_GetZero() and _PyLong_GetOne()
15+
static inline PyObject* __PyLong_GetSmallInt_internal(int value)
16+
{
17+
PyThreadState *tstate = _PyThreadState_GET();
18+
#ifdef Py_DEBUG
19+
_Py_EnsureTstateNotNULL(tstate);
20+
#endif
21+
assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS);
22+
size_t index = _PY_NSMALLNEGINTS + value;
23+
PyObject *obj = (PyObject*)tstate->interp->small_ints[index];
24+
// _PyLong_GetZero() and _PyLong_GetOne() must not be called
25+
// before _PyLong_Init() nor after _PyLong_Fini()
26+
assert(obj != NULL);
27+
return obj;
28+
}
29+
30+
// Return a borrowed reference to the zero singleton.
31+
// The function cannot return NULL.
32+
static inline PyObject* _PyLong_GetZero(void)
33+
{ return __PyLong_GetSmallInt_internal(0); }
34+
35+
// Return a borrowed reference to the one singleton.
36+
// The function cannot return NULL.
37+
static inline PyObject* _PyLong_GetOne(void)
38+
{ return __PyLong_GetSmallInt_internal(1); }
39+
40+
#ifdef __cplusplus
41+
}
42+
#endif
43+
#endif /* !Py_INTERNAL_LONG_H */

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,7 @@ PYTHON_HEADERS= \
11171117
$(srcdir)/Include/internal/pycore_initconfig.h \
11181118
$(srcdir)/Include/internal/pycore_interp.h \
11191119
$(srcdir)/Include/internal/pycore_list.h \
1120+
$(srcdir)/Include/internal/pycore_long.h \
11201121
$(srcdir)/Include/internal/pycore_object.h \
11211122
$(srcdir)/Include/internal/pycore_pathconfig.h \
11221123
$(srcdir)/Include/internal/pycore_pyerrors.h \

Objects/longobject.c

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "Python.h"
66
#include "pycore_bitutils.h" // _Py_popcount32()
77
#include "pycore_interp.h" // _PY_NSMALLPOSINTS
8+
#include "pycore_long.h" // __PyLong_GetSmallInt_internal()
89
#include "pycore_object.h" // _PyObject_InitVar()
910
#include "pycore_pystate.h" // _Py_IsMainInterpreter()
1011
#include "longintrepr.h"
@@ -19,8 +20,8 @@ class int "PyObject *" "&PyLong_Type"
1920
[clinic start generated code]*/
2021
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ec0275e3422a36e3]*/
2122

22-
#define NSMALLPOSINTS _PY_NSMALLPOSINTS
2323
#define NSMALLNEGINTS _PY_NSMALLNEGINTS
24+
#define NSMALLPOSINTS _PY_NSMALLPOSINTS
2425

2526
_Py_IDENTIFIER(little);
2627
_Py_IDENTIFIER(big);
@@ -34,16 +35,14 @@ _Py_IDENTIFIER(big);
3435
PyObject *_PyLong_Zero = NULL;
3536
PyObject *_PyLong_One = NULL;
3637

37-
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
3838
#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
3939
#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
4040

4141
static PyObject *
4242
get_small_int(sdigit ival)
4343
{
4444
assert(IS_SMALL_INT(ival));
45-
PyInterpreterState *interp = _PyInterpreterState_GET();
46-
PyObject *v = (PyObject*)interp->small_ints[ival + NSMALLNEGINTS];
45+
PyObject *v = __PyLong_GetSmallInt_internal(ival);
4746
Py_INCREF(v);
4847
return v;
4948
}
@@ -60,12 +59,6 @@ maybe_small_long(PyLongObject *v)
6059
}
6160
return v;
6261
}
63-
#else
64-
#define IS_SMALL_INT(ival) 0
65-
#define IS_SMALL_UINT(ival) 0
66-
#define get_small_int(ival) (Py_UNREACHABLE(), NULL)
67-
#define maybe_small_long(val) (val)
68-
#endif
6962

7063
/* If a freshly-allocated int is already shared, it must
7164
be a small integer, so negating it must go to PyLong_FromLong */
@@ -2559,8 +2552,9 @@ long_divrem(PyLongObject *a, PyLongObject *b,
25592552
if (*prem == NULL) {
25602553
return -1;
25612554
}
2562-
Py_INCREF(_PyLong_Zero);
2563-
*pdiv = (PyLongObject*)_PyLong_Zero;
2555+
PyObject *zero = _PyLong_GetZero();
2556+
Py_INCREF(zero);
2557+
*pdiv = (PyLongObject*)zero;
25642558
return 0;
25652559
}
25662560
if (size_b == 1) {
@@ -3669,7 +3663,7 @@ l_divmod(PyLongObject *v, PyLongObject *w,
36693663
Py_DECREF(div);
36703664
return -1;
36713665
}
3672-
temp = (PyLongObject *) long_sub(div, (PyLongObject *)_PyLong_One);
3666+
temp = (PyLongObject *) long_sub(div, (PyLongObject *)_PyLong_GetOne());
36733667
if (temp == NULL) {
36743668
Py_DECREF(mod);
36753669
Py_DECREF(div);
@@ -4078,7 +4072,7 @@ long_invmod(PyLongObject *a, PyLongObject *n)
40784072

40794073
Py_DECREF(c);
40804074
Py_DECREF(n);
4081-
if (long_compare(a, (PyLongObject *)_PyLong_One)) {
4075+
if (long_compare(a, (PyLongObject *)_PyLong_GetOne())) {
40824076
/* a != 1; we don't have an inverse. */
40834077
Py_DECREF(a);
40844078
Py_DECREF(b);
@@ -4313,7 +4307,7 @@ long_invert(PyLongObject *v)
43134307
PyLongObject *x;
43144308
if (Py_ABS(Py_SIZE(v)) <=1)
43154309
return PyLong_FromLong(-(MEDIUM_VALUE(v)+1));
4316-
x = (PyLongObject *) long_add(v, (PyLongObject *)_PyLong_One);
4310+
x = (PyLongObject *) long_add(v, (PyLongObject *)_PyLong_GetOne());
43174311
if (x == NULL)
43184312
return NULL;
43194313
_PyLong_Negate(&x);
@@ -5105,7 +5099,8 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b)
51055099

51065100
/* compare twice the remainder with the divisor, to see
51075101
if we need to adjust the quotient and remainder */
5108-
twice_rem = long_lshift((PyObject *)rem, _PyLong_One);
5102+
PyObject *one = _PyLong_GetOne(); // borrowed reference
5103+
twice_rem = long_lshift((PyObject *)rem, one);
51095104
if (twice_rem == NULL)
51105105
goto error;
51115106
if (quo_is_neg) {
@@ -5122,9 +5117,9 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b)
51225117
if ((Py_SIZE(b) < 0 ? cmp < 0 : cmp > 0) || (cmp == 0 && quo_is_odd)) {
51235118
/* fix up quotient */
51245119
if (quo_is_neg)
5125-
temp = long_sub(quo, (PyLongObject *)_PyLong_One);
5120+
temp = long_sub(quo, (PyLongObject *)one);
51265121
else
5127-
temp = long_add(quo, (PyLongObject *)_PyLong_One);
5122+
temp = long_add(quo, (PyLongObject *)one);
51285123
Py_DECREF(quo);
51295124
quo = (PyLongObject *)temp;
51305125
if (quo == NULL)
@@ -5406,7 +5401,7 @@ int_as_integer_ratio_impl(PyObject *self)
54065401
if (numerator == NULL) {
54075402
return NULL;
54085403
}
5409-
ratio_tuple = PyTuple_Pack(2, numerator, _PyLong_One);
5404+
ratio_tuple = PyTuple_Pack(2, numerator, _PyLong_GetOne());
54105405
Py_DECREF(numerator);
54115406
return ratio_tuple;
54125407
}
@@ -5712,7 +5707,6 @@ PyLong_GetInfo(void)
57125707
int
57135708
_PyLong_Init(PyThreadState *tstate)
57145709
{
5715-
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
57165710
for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
57175711
sdigit ival = (sdigit)i - NSMALLNEGINTS;
57185712
int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
@@ -5727,7 +5721,6 @@ _PyLong_Init(PyThreadState *tstate)
57275721

57285722
tstate->interp->small_ints[i] = v;
57295723
}
5730-
#endif
57315724

57325725
if (_Py_IsMainInterpreter(tstate)) {
57335726
_PyLong_Zero = PyLong_FromLong(0);
@@ -5759,9 +5752,7 @@ _PyLong_Fini(PyThreadState *tstate)
57595752
Py_CLEAR(_PyLong_Zero);
57605753
}
57615754

5762-
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
57635755
for (Py_ssize_t i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
57645756
Py_CLEAR(tstate->interp->small_ints[i]);
57655757
}
5766-
#endif
57675758
}

PCbuild/pythoncore.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@
185185
<ClInclude Include="..\Include\internal\pycore_initconfig.h" />
186186
<ClInclude Include="..\Include\internal\pycore_interp.h" />
187187
<ClInclude Include="..\Include\internal\pycore_list.h" />
188+
<ClInclude Include="..\Include\internal\pycore_long.h" />
188189
<ClInclude Include="..\Include\internal\pycore_object.h" />
189190
<ClInclude Include="..\Include\internal\pycore_pathconfig.h" />
190191
<ClInclude Include="..\Include\internal\pycore_pyerrors.h" />

PCbuild/pythoncore.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,9 @@
537537
<ClInclude Include="..\Include\internal\pycore_list.h">
538538
<Filter>Include\internal</Filter>
539539
</ClInclude>
540+
<ClInclude Include="..\Include\internal\pycore_long.h">
541+
<Filter>Include\internal</Filter>
542+
</ClInclude>
540543
<ClInclude Include="..\Include\internal\pycore_object.h">
541544
<Filter>Include\internal</Filter>
542545
</ClInclude>

0 commit comments

Comments
 (0)