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
structast_stateast;
10021002
structtypes_statetypes;
10031003
structcallable_cachecallable_cache;
1004-
PyObject*common_consts[NUM_COMMON_CONSTANTS];
1004+
_PyStackRefcommon_consts[NUM_COMMON_CONSTANTS];
10051005
booljit;
10061006
boolcompiling;
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
#definePyStackRef_DUP(REF) _PyStackRef_DUP(REF, __FILE__, __LINE__)
265265

266+
staticinline_PyStackRef
267+
_PyStackRef_DupImmortal(_PyStackRefref, constchar*filename, intlinenumber)
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+
#definePyStackRef_DupImmortal(REF) _PyStackRef_DupImmortal((REF), __FILE__, __LINE__)
277+
266278
staticinlinevoid
267279
_PyStackRef_CLOSE_SPECIALIZED(_PyStackRefref, destructordestruct, constchar*filename, intlinenumber)
268280
{
@@ -633,6 +645,15 @@ PyStackRef_DUP(_PyStackRef ref)
633645
}
634646
#endif
635647

648+
staticinline_PyStackRef
649+
PyStackRef_DupImmortal(_PyStackRefref)
650+
{
651+
assert(!PyStackRef_IsNull(ref));
652+
assert(!PyStackRef_RefcountOnObject(ref));
653+
assert(_Py_IsImmortal(BITS_TO_PTR_MASKED(ref)));
654+
returnref;
655+
}
656+
636657
staticinlinebool
637658
PyStackRef_IsHeapSafe(_PyStackRefref)
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-
returnPy_NewRef(_PyInterpreterState_GET()->common_consts[oparg]);
1334+
returnPyStackRef_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 (inti=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)