mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
bpo-38858: Small integer per interpreter (GH-17315)
Each Python subinterpreter now has its own "small integer singletons": numbers in [-5; 257] range. It is no longer possible to change the number of small integers at build time by overriding NSMALLNEGINTS and NSMALLPOSINTS macros: macros should now be modified manually in pycore_pystate.h header file. For now, continue to share _PyLong_Zero and _PyLong_One singletons between all subinterpreters.
This commit is contained in:
parent
f501db2b93
commit
630c8df5cf
5 changed files with 57 additions and 38 deletions
|
@ -33,7 +33,7 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
|
||||||
|
|
||||||
extern PyStatus _PyUnicode_Init(void);
|
extern PyStatus _PyUnicode_Init(void);
|
||||||
extern int _PyStructSequence_Init(void);
|
extern int _PyStructSequence_Init(void);
|
||||||
extern int _PyLong_Init(void);
|
extern int _PyLong_Init(PyThreadState *tstate);
|
||||||
extern PyStatus _PyFaulthandler_Init(int enable);
|
extern PyStatus _PyFaulthandler_Init(int enable);
|
||||||
extern int _PyTraceMalloc_Init(int enable);
|
extern int _PyTraceMalloc_Init(int enable);
|
||||||
extern PyObject * _PyBuiltin_Init(PyThreadState *tstate);
|
extern PyObject * _PyBuiltin_Init(PyThreadState *tstate);
|
||||||
|
@ -76,7 +76,7 @@ extern void _PyGC_Fini(PyThreadState *tstate);
|
||||||
extern void _PyType_Fini(void);
|
extern void _PyType_Fini(void);
|
||||||
extern void _Py_HashRandomization_Fini(void);
|
extern void _Py_HashRandomization_Fini(void);
|
||||||
extern void _PyUnicode_Fini(PyThreadState *tstate);
|
extern void _PyUnicode_Fini(PyThreadState *tstate);
|
||||||
extern void _PyLong_Fini(void);
|
extern void _PyLong_Fini(PyThreadState *tstate);
|
||||||
extern void _PyFaulthandler_Fini(void);
|
extern void _PyFaulthandler_Fini(void);
|
||||||
extern void _PyHash_Fini(void);
|
extern void _PyHash_Fini(void);
|
||||||
extern void _PyTraceMalloc_Fini(void);
|
extern void _PyTraceMalloc_Fini(void);
|
||||||
|
|
|
@ -56,6 +56,9 @@ struct _ceval_runtime_state {
|
||||||
|
|
||||||
typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
|
typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
|
||||||
|
|
||||||
|
#define _PY_NSMALLPOSINTS 257
|
||||||
|
#define _PY_NSMALLNEGINTS 5
|
||||||
|
|
||||||
// The PyInterpreterState typedef is in Include/pystate.h.
|
// The PyInterpreterState typedef is in Include/pystate.h.
|
||||||
struct _is {
|
struct _is {
|
||||||
|
|
||||||
|
@ -139,6 +142,15 @@ struct _is {
|
||||||
int atbol;
|
int atbol;
|
||||||
} listnode;
|
} listnode;
|
||||||
} parser;
|
} parser;
|
||||||
|
|
||||||
|
#if _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS > 0
|
||||||
|
/* Small integers are preallocated in this array so that they
|
||||||
|
can be shared.
|
||||||
|
The integers that are preallocated are those in the range
|
||||||
|
-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive).
|
||||||
|
*/
|
||||||
|
PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(PY_INT64_T);
|
PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(PY_INT64_T);
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Each Python subinterpreter now has its own "small integer singletons":
|
||||||
|
numbers in [-5; 257] range. It is no longer possible to change the number of
|
||||||
|
small integers at build time by overriding ``NSMALLNEGINTS`` and
|
||||||
|
``NSMALLPOSINTS`` macros: macros should now be modified manually in
|
||||||
|
``pycore_pystate.h`` header file.
|
|
@ -3,6 +3,7 @@
|
||||||
/* XXX The functional organization of this file is terrible */
|
/* XXX The functional organization of this file is terrible */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_pystate.h" /* _Py_IsMainInterpreter() */
|
||||||
#include "longintrepr.h"
|
#include "longintrepr.h"
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
@ -15,12 +16,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]*/
|
||||||
|
|
||||||
#ifndef NSMALLPOSINTS
|
#define NSMALLPOSINTS _PY_NSMALLPOSINTS
|
||||||
#define NSMALLPOSINTS 257
|
#define NSMALLNEGINTS _PY_NSMALLNEGINTS
|
||||||
#endif
|
|
||||||
#ifndef NSMALLNEGINTS
|
|
||||||
#define NSMALLNEGINTS 5
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_Py_IDENTIFIER(little);
|
_Py_IDENTIFIER(little);
|
||||||
_Py_IDENTIFIER(big);
|
_Py_IDENTIFIER(big);
|
||||||
|
@ -35,13 +32,6 @@ PyObject *_PyLong_Zero = NULL;
|
||||||
PyObject *_PyLong_One = NULL;
|
PyObject *_PyLong_One = NULL;
|
||||||
|
|
||||||
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
||||||
/* Small integers are preallocated in this array so that they
|
|
||||||
can be shared.
|
|
||||||
The integers that are preallocated are those in the range
|
|
||||||
-NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
|
|
||||||
*/
|
|
||||||
static PyLongObject* small_ints[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)
|
||||||
|
|
||||||
|
@ -53,7 +43,8 @@ static PyObject *
|
||||||
get_small_int(sdigit ival)
|
get_small_int(sdigit ival)
|
||||||
{
|
{
|
||||||
assert(IS_SMALL_INT(ival));
|
assert(IS_SMALL_INT(ival));
|
||||||
PyObject *v = (PyObject*)small_ints[ival + NSMALLNEGINTS];
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
PyObject *v = (PyObject*)tstate->interp->small_ints[ival + NSMALLNEGINTS];
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
if (ival >= 0)
|
if (ival >= 0)
|
||||||
|
@ -5782,7 +5773,7 @@ PyLong_GetInfo(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyLong_Init(void)
|
_PyLong_Init(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
||||||
for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
|
for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
|
||||||
|
@ -5797,37 +5788,43 @@ _PyLong_Init(void)
|
||||||
Py_SIZE(v) = size;
|
Py_SIZE(v) = size;
|
||||||
v->ob_digit[0] = (digit)abs(ival);
|
v->ob_digit[0] = (digit)abs(ival);
|
||||||
|
|
||||||
small_ints[i] = v;
|
tstate->interp->small_ints[i] = v;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_PyLong_Zero = PyLong_FromLong(0);
|
|
||||||
if (_PyLong_Zero == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_PyLong_One = PyLong_FromLong(1);
|
if (_Py_IsMainInterpreter(tstate)) {
|
||||||
if (_PyLong_One == NULL) {
|
_PyLong_Zero = PyLong_FromLong(0);
|
||||||
return 0;
|
if (_PyLong_Zero == NULL) {
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize int_info */
|
|
||||||
if (Int_InfoType.tp_name == NULL) {
|
|
||||||
if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_PyLong_One = PyLong_FromLong(1);
|
||||||
|
if (_PyLong_One == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize int_info */
|
||||||
|
if (Int_InfoType.tp_name == NULL) {
|
||||||
|
if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyLong_Fini(void)
|
_PyLong_Fini(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
Py_CLEAR(_PyLong_One);
|
if (_Py_IsMainInterpreter(tstate)) {
|
||||||
Py_CLEAR(_PyLong_Zero);
|
Py_CLEAR(_PyLong_One);
|
||||||
|
Py_CLEAR(_PyLong_Zero);
|
||||||
|
}
|
||||||
|
|
||||||
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
#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(small_ints[i]);
|
Py_CLEAR(tstate->interp->small_ints[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -576,10 +576,11 @@ pycore_init_types(PyThreadState *tstate)
|
||||||
if (_PyStatus_EXCEPTION(status)) {
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!_PyLong_Init()) {
|
|
||||||
return _PyStatus_ERR("can't init longs");
|
if (!_PyLong_Init(tstate)) {
|
||||||
}
|
return _PyStatus_ERR("can't init longs");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_main_interp) {
|
if (is_main_interp) {
|
||||||
|
@ -1251,7 +1252,11 @@ finalize_interp_types(PyThreadState *tstate, int is_main_interp)
|
||||||
_PyList_Fini();
|
_PyList_Fini();
|
||||||
_PySet_Fini();
|
_PySet_Fini();
|
||||||
_PyBytes_Fini();
|
_PyBytes_Fini();
|
||||||
_PyLong_Fini();
|
}
|
||||||
|
|
||||||
|
_PyLong_Fini(tstate);
|
||||||
|
|
||||||
|
if (is_main_interp) {
|
||||||
_PyFloat_Fini();
|
_PyFloat_Fini();
|
||||||
_PyDict_Fini();
|
_PyDict_Fini();
|
||||||
_PySlice_Fini();
|
_PySlice_Fini();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue