Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Include/internal/pycore_interp_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ struct _is {
struct ast_state ast;
struct types_state types;
struct callable_cache callable_cache;
PyObject *common_consts[NUM_COMMON_CONSTANTS];
_PyStackRef common_consts[NUM_COMMON_CONSTANTS];
bool jit;
bool compiling;

Expand Down
2 changes: 1 addition & 1 deletion Modules/_testinternalcapi/test_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1972,7 +1972,7 @@ dummy_func(
inst(LOAD_COMMON_CONSTANT, ( -- value)) {
// Keep in sync with _common_constants in opcode.py
assert(oparg < NUM_COMMON_CONSTANTS);
value = PyStackRef_FromPyObjectNew(tstate->interp->common_consts[oparg]);
value = PyStackRef_DUP(tstate->interp->common_consts[oparg]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to check the tag.

Could you add PyStackRef_DupImmortal(ref) which would return its argument unchanged and assert that the referenced object is immortal, otherwise it defeats the point of changing PyObject * to _PyStackRef here

}

inst(LOAD_BUILD_CLASS, ( -- bc)) {
Expand Down
6 changes: 3 additions & 3 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Python/flowgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "pycore_opcode_utils.h"
#include "pycore_opcode_metadata.h" // OPCODE_HAS_ARG, etc
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_stackref.h" // PyStackRef_AsPyObjectBorrow()

#include <stdbool.h>

Expand Down Expand Up @@ -1330,7 +1331,8 @@ get_const_value(int opcode, int oparg, PyObject *co_consts)
}
if (opcode == LOAD_COMMON_CONSTANT) {
assert(oparg < NUM_COMMON_CONSTANTS);
return Py_NewRef(_PyInterpreterState_GET()->common_consts[oparg]);
return Py_NewRef(PyStackRef_AsPyObjectBorrow(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return Py_NewRef(PyStackRef_AsPyObjectBorrow(
return PyStackRef_AsPyObjectBorrow(

These objects are immortal, you can borrow references to them.

_PyInterpreterState_GET()->common_consts[oparg]));
}

if (constant == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 6 additions & 9 deletions Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "pycore_long.h"
#include "pycore_opcode_utils.h"
#include "pycore_optimizer.h"
#include "pycore_stackref.h"
#include "pycore_typeobject.h"
#include "pycore_uops.h"
#include "pycore_uop_ids.h"
Expand Down Expand Up @@ -870,15 +871,11 @@ dummy_func(void) {

op(_LOAD_COMMON_CONSTANT, (-- value)) {
assert(oparg < NUM_COMMON_CONSTANTS);
PyObject *val = _PyInterpreterState_GET()->common_consts[oparg];
if (_Py_IsImmortal(val)) {
ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
value = PyJitRef_Borrow(sym_new_const(ctx, val));
}
else {
ADD_OP(_LOAD_CONST_INLINE, 0, (uintptr_t)val);
value = sym_new_const(ctx, val);
}
PyObject *val = PyStackRef_AsPyObjectBorrow(
_PyInterpreterState_GET()->common_consts[oparg]);
assert(_Py_IsImmortal(val));
ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
value = PyJitRef_Borrow(sym_new_const(ctx, val));
}

op(_LOAD_SMALL_INT, (-- value)) {
Expand Down
14 changes: 5 additions & 9 deletions Python/optimizer_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 17 additions & 13 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "pycore_runtime.h" // _Py_ID()
#include "pycore_runtime_init.h" // _PyRuntimeState_INIT
#include "pycore_setobject.h" // _PySet_NextEntry()
#include "pycore_stackref.h" // PyStackRef_FromPyObjectBorrow()
#include "pycore_stats.h" // _PyStats_InterpInit()
#include "pycore_sysmodule.h" // _PySys_ClearAttrString()
#include "pycore_traceback.h" // PyUnstable_TracebackThreads()
Expand Down Expand Up @@ -878,22 +879,25 @@ pycore_init_builtins(PyThreadState *tstate)
goto error;
}

interp->common_consts[CONSTANT_ASSERTIONERROR] = PyExc_AssertionError;
interp->common_consts[CONSTANT_NOTIMPLEMENTEDERROR] = PyExc_NotImplementedError;
interp->common_consts[CONSTANT_BUILTIN_TUPLE] = (PyObject *)&PyTuple_Type;
interp->common_consts[CONSTANT_BUILTIN_ALL] = all;
interp->common_consts[CONSTANT_BUILTIN_ANY] = any;
interp->common_consts[CONSTANT_BUILTIN_LIST] = (PyObject *)&PyList_Type;
interp->common_consts[CONSTANT_BUILTIN_SET] = (PyObject *)&PySet_Type;
interp->common_consts[CONSTANT_NONE] = Py_None;
interp->common_consts[CONSTANT_EMPTY_STR] =
PyObject *common_objs[NUM_COMMON_CONSTANTS] = {NULL};
common_objs[CONSTANT_ASSERTIONERROR] = PyExc_AssertionError;
common_objs[CONSTANT_NOTIMPLEMENTEDERROR] = PyExc_NotImplementedError;
common_objs[CONSTANT_BUILTIN_TUPLE] = (PyObject *)&PyTuple_Type;
common_objs[CONSTANT_BUILTIN_ALL] = all;
common_objs[CONSTANT_BUILTIN_ANY] = any;
common_objs[CONSTANT_BUILTIN_LIST] = (PyObject *)&PyList_Type;
common_objs[CONSTANT_BUILTIN_SET] = (PyObject *)&PySet_Type;
common_objs[CONSTANT_NONE] = Py_None;
common_objs[CONSTANT_EMPTY_STR] =
Py_GetConstantBorrowed(Py_CONSTANT_EMPTY_STR);
interp->common_consts[CONSTANT_TRUE] = Py_True;
interp->common_consts[CONSTANT_FALSE] = Py_False;
interp->common_consts[CONSTANT_MINUS_ONE] =
common_objs[CONSTANT_TRUE] = Py_True;
common_objs[CONSTANT_FALSE] = Py_False;
common_objs[CONSTANT_MINUS_ONE] =
(PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS - 1];
for (int i = 0; i < NUM_COMMON_CONSTANTS; i++) {
assert(interp->common_consts[i] != NULL);
assert(common_objs[i] != NULL);
_Py_SetImmortal(common_objs[i]);
interp->common_consts[i] = PyStackRef_FromPyObjectBorrow(common_objs[i]);
}

PyObject *list_append = _PyType_Lookup(&PyList_Type, &_Py_ID(append));
Expand Down
36 changes: 34 additions & 2 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@
#include "pycore_freelist.h" // _PyObject_ClearFreeLists()
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_interpframe.h" // _PyThreadState_HasStackSpace()
#include "pycore_object.h" // _PyType_InitCache()
#include "pycore_object.h" // _PyType_InitCache(), _Py_ClearImmortal()
#include "pycore_obmalloc.h" // _PyMem_obmalloc_state_on_heap()
#include "pycore_opcode_utils.h" // NUM_COMMON_CONSTANTS
#include "pycore_optimizer.h" // JIT_CLEANUP_THRESHOLD
#include "pycore_parking_lot.h" // _PyParkingLot_AfterFork()
#include "pycore_pyerrors.h" // _PyErr_Clear()
#include "pycore_pylifecycle.h" // _PyAST_Fini()
#include "pycore_pymem.h" // _PyMem_DebugEnabled()
#include "pycore_runtime.h" // _PyRuntime
#include "pycore_runtime_init.h" // _PyRuntimeState_INIT
#include "pycore_stackref.h" // Py_STACKREF_DEBUG
#include "pycore_stackref.h" // PyStackRef_AsPyObjectBorrow()
#include "pycore_stats.h" // FT_STAT_WORLD_STOP_INC()
#include "pycore_time.h" // _PyTime_Init()
#include "pycore_uniqueid.h" // _PyObject_FinalizePerThreadRefcounts()
Expand Down Expand Up @@ -777,6 +778,36 @@ extern void
_Py_stackref_report_leaks(PyInterpreterState *interp);
#endif

static int
common_const_is_initialized(_PyStackRef ref)
{
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
return !PyStackRef_IsNull(ref);
#else
return ref.bits != 0 && !PyStackRef_IsNull(ref);
#endif
}


static void
common_constants_clear(PyInterpreterState *interp)
{
for (int i = 0; i < NUM_COMMON_CONSTANTS; i++) {
_PyStackRef ref = interp->common_consts[i];
if (!common_const_is_initialized(ref)) {
continue;
}
PyObject *obj = PyStackRef_AsPyObjectBorrow(ref);
PyStackRef_XCLOSE(ref);
interp->common_consts[i] = PyStackRef_NULL;
// Refcount reclamation skips heap immortals; release manually.
if (_Py_IsImmortal(obj) && !_Py_IsStaticImmortal(obj)) {
_Py_ClearImmortal(obj);
}
}
}


static void
interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
{
Expand Down Expand Up @@ -903,6 +934,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
PyDict_Clear(interp->builtins);
Py_CLEAR(interp->sysdict);
Py_CLEAR(interp->builtins);
common_constants_clear(interp);

#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
# ifdef Py_STACKREF_CLOSE_DEBUG
Expand Down
Loading