Skip to content

Commit 39bd44f

Browse files
authored
gh-148871: make LOAD_COMMON_CONSTANT use immortal stackref borrows (GH-149625)
1 parent 2531cd3 commit 39bd44f

12 files changed

Lines changed: 96 additions & 43 deletions

File tree

Include/internal/pycore_interp_structs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ struct _is {
10011001
struct ast_state ast;
10021002
struct types_state types;
10031003
struct callable_cache callable_cache;
1004-
PyObject *common_consts[NUM_COMMON_CONSTANTS];
1004+
_PyStackRef common_consts[NUM_COMMON_CONSTANTS];
10051005
bool jit;
10061006
bool compiling;
10071007

Include/internal/pycore_stackref.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,18 @@ _PyStackRef_DUP(_PyStackRef ref, const char *filename, int linenumber)
263263
}
264264
#define PyStackRef_DUP(REF) _PyStackRef_DUP(REF, __FILE__, __LINE__)
265265

266+
static inline _PyStackRef
267+
_PyStackRef_DupImmortal(_PyStackRef ref, const char *filename, int linenumber)
268+
{
269+
assert(!PyStackRef_IsError(ref));
270+
assert(!PyStackRef_IsTaggedInt(ref));
271+
assert(!PyStackRef_RefcountOnObject(ref));
272+
PyObject *obj = _Py_stackref_get_object(ref);
273+
assert(_Py_IsImmortal(obj));
274+
return _Py_stackref_create(obj, Py_TAG_REFCNT, filename, linenumber);
275+
}
276+
#define PyStackRef_DupImmortal(REF) _PyStackRef_DupImmortal((REF), __FILE__, __LINE__)
277+
266278
static inline void
267279
_PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct, const char *filename, int linenumber)
268280
{
@@ -633,6 +645,15 @@ PyStackRef_DUP(_PyStackRef ref)
633645
}
634646
#endif
635647

648+
static inline _PyStackRef
649+
PyStackRef_DupImmortal(_PyStackRef ref)
650+
{
651+
assert(!PyStackRef_IsNull(ref));
652+
assert(!PyStackRef_RefcountOnObject(ref));
653+
assert(_Py_IsImmortal(BITS_TO_PTR_MASKED(ref)));
654+
return ref;
655+
}
656+
636657
static inline bool
637658
PyStackRef_IsHeapSafe(_PyStackRef ref)
638659
{

Modules/_testinternalcapi/test_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/bytecodes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1974,7 +1974,7 @@ dummy_func(
19741974
inst(LOAD_COMMON_CONSTANT, ( -- value)) {
19751975
// Keep in sync with _common_constants in opcode.py
19761976
assert(oparg < NUM_COMMON_CONSTANTS);
1977-
value = PyStackRef_FromPyObjectNew(tstate->interp->common_consts[oparg]);
1977+
value = PyStackRef_DupImmortal(tstate->interp->common_consts[oparg]);
19781978
}
19791979

19801980
inst(LOAD_BUILD_CLASS, ( -- bc)) {

Python/executor_cases.c.h

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/flowgraph.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "pycore_opcode_utils.h"
1212
#include "pycore_opcode_metadata.h" // OPCODE_HAS_ARG, etc
1313
#include "pycore_pystate.h" // _PyInterpreterState_GET()
14+
#include "pycore_stackref.h" // PyStackRef_AsPyObjectBorrow()
1415

1516
#include <stdbool.h>
1617

@@ -1330,7 +1331,8 @@ get_const_value(int opcode, int oparg, PyObject *co_consts)
13301331
}
13311332
if (opcode == LOAD_COMMON_CONSTANT) {
13321333
assert(oparg < NUM_COMMON_CONSTANTS);
1333-
return Py_NewRef(_PyInterpreterState_GET()->common_consts[oparg]);
1334+
return PyStackRef_AsPyObjectBorrow(
1335+
_PyInterpreterState_GET()->common_consts[oparg]);
13341336
}
13351337

13361338
if (constant == NULL) {

Python/generated_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer_bytecodes.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "pycore_long.h"
33
#include "pycore_opcode_utils.h"
44
#include "pycore_optimizer.h"
5+
#include "pycore_stackref.h"
56
#include "pycore_typeobject.h"
67
#include "pycore_uops.h"
78
#include "pycore_uop_ids.h"
@@ -870,15 +871,11 @@ dummy_func(void) {
870871

871872
op(_LOAD_COMMON_CONSTANT, (-- value)) {
872873
assert(oparg < NUM_COMMON_CONSTANTS);
873-
PyObject *val = _PyInterpreterState_GET()->common_consts[oparg];
874-
if (_Py_IsImmortal(val)) {
875-
ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
876-
value = PyJitRef_Borrow(sym_new_const(ctx, val));
877-
}
878-
else {
879-
ADD_OP(_LOAD_CONST_INLINE, 0, (uintptr_t)val);
880-
value = sym_new_const(ctx, val);
881-
}
874+
PyObject *val = PyStackRef_AsPyObjectBorrow(
875+
_PyInterpreterState_GET()->common_consts[oparg]);
876+
assert(_Py_IsImmortal(val));
877+
ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
878+
value = PyJitRef_Borrow(sym_new_const(ctx, val));
882879
}
883880

884881
op(_LOAD_SMALL_INT, (-- value)) {

Python/optimizer_cases.c.h

Lines changed: 5 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/pylifecycle.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "pycore_runtime.h" // _Py_ID()
2929
#include "pycore_runtime_init.h" // _PyRuntimeState_INIT
3030
#include "pycore_setobject.h" // _PySet_NextEntry()
31+
#include "pycore_stackref.h" // PyStackRef_FromPyObjectBorrow()
3132
#include "pycore_stats.h" // _PyStats_InterpInit()
3233
#include "pycore_sysmodule.h" // _PySys_ClearAttrString()
3334
#include "pycore_traceback.h" // PyUnstable_TracebackThreads()
@@ -878,25 +879,28 @@ pycore_init_builtins(PyThreadState *tstate)
878879
goto error;
879880
}
880881

881-
interp->common_consts[CONSTANT_ASSERTIONERROR] = PyExc_AssertionError;
882-
interp->common_consts[CONSTANT_NOTIMPLEMENTEDERROR] = PyExc_NotImplementedError;
883-
interp->common_consts[CONSTANT_BUILTIN_TUPLE] = (PyObject *)&PyTuple_Type;
884-
interp->common_consts[CONSTANT_BUILTIN_ALL] = all;
885-
interp->common_consts[CONSTANT_BUILTIN_ANY] = any;
886-
interp->common_consts[CONSTANT_BUILTIN_LIST] = (PyObject *)&PyList_Type;
887-
interp->common_consts[CONSTANT_BUILTIN_SET] = (PyObject *)&PySet_Type;
888-
interp->common_consts[CONSTANT_NONE] = Py_None;
889-
interp->common_consts[CONSTANT_EMPTY_STR] =
882+
PyObject *common_objs[NUM_COMMON_CONSTANTS] = {NULL};
883+
common_objs[CONSTANT_ASSERTIONERROR] = PyExc_AssertionError;
884+
common_objs[CONSTANT_NOTIMPLEMENTEDERROR] = PyExc_NotImplementedError;
885+
common_objs[CONSTANT_BUILTIN_TUPLE] = (PyObject *)&PyTuple_Type;
886+
common_objs[CONSTANT_BUILTIN_ALL] = all;
887+
common_objs[CONSTANT_BUILTIN_ANY] = any;
888+
common_objs[CONSTANT_BUILTIN_LIST] = (PyObject *)&PyList_Type;
889+
common_objs[CONSTANT_BUILTIN_SET] = (PyObject *)&PySet_Type;
890+
common_objs[CONSTANT_NONE] = Py_None;
891+
common_objs[CONSTANT_EMPTY_STR] =
890892
Py_GetConstantBorrowed(Py_CONSTANT_EMPTY_STR);
891-
interp->common_consts[CONSTANT_TRUE] = Py_True;
892-
interp->common_consts[CONSTANT_FALSE] = Py_False;
893-
interp->common_consts[CONSTANT_MINUS_ONE] =
893+
common_objs[CONSTANT_TRUE] = Py_True;
894+
common_objs[CONSTANT_FALSE] = Py_False;
895+
common_objs[CONSTANT_MINUS_ONE] =
894896
(PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS - 1];
895-
interp->common_consts[CONSTANT_BUILTIN_FROZENSET] = (PyObject *)&PyFrozenSet_Type;
896-
interp->common_consts[CONSTANT_EMPTY_TUPLE] =
897+
common_objs[CONSTANT_BUILTIN_FROZENSET] = (PyObject *)&PyFrozenSet_Type;
898+
common_objs[CONSTANT_EMPTY_TUPLE] =
897899
Py_GetConstantBorrowed(Py_CONSTANT_EMPTY_TUPLE);
898900
for (int i = 0; i < NUM_COMMON_CONSTANTS; i++) {
899-
assert(interp->common_consts[i] != NULL);
901+
assert(common_objs[i] != NULL);
902+
_Py_SetImmortal(common_objs[i]);
903+
interp->common_consts[i] = PyStackRef_FromPyObjectBorrow(common_objs[i]);
900904
}
901905

902906
PyObject *list_append = _PyType_Lookup(&PyList_Type, &_Py_ID(append));

0 commit comments

Comments
 (0)