https://github.com/python/cpython/commit/96ff4c2486e0c3efb62ce3e712c9bd919dbb6b20
commit: 96ff4c2486e0c3efb62ce3e712c9bd919dbb6b20
branch: main
author: Mark Shannon <[email protected]>
committer: markshannon <[email protected]>
date: 2025-02-04T14:00:51Z
summary:
GH-128682: Mark two more macros as escaping. (GH-129645)
Expand out SETLOCAL so that code generator can see the decref. Mark Py_CLEAR as
escaping
files:
M Python/bytecodes.c
M Python/ceval.c
M Python/ceval_macros.h
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Tools/cases_generator/analyzer.py
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index cb88ba74f9a5fe..b650613650cf36 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -272,7 +272,6 @@ dummy_func(
inst(LOAD_FAST_AND_CLEAR, (-- value)) {
value = GETLOCAL(oparg);
- // do not use SETLOCAL here, it decrefs the old value
GETLOCAL(oparg) = PyStackRef_NULL;
}
@@ -328,8 +327,10 @@ dummy_func(
}
replicate(8) inst(STORE_FAST, (value --)) {
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
DEAD(value);
+ PyStackRef_XCLOSE(tmp);
}
pseudo(STORE_FAST_MAYBE_NULL, (unused --)) = {
@@ -339,18 +340,24 @@ dummy_func(
inst(STORE_FAST_LOAD_FAST, (value1 -- value2)) {
uint32_t oparg1 = oparg >> 4;
uint32_t oparg2 = oparg & 15;
- SETLOCAL(oparg1, value1);
+ _PyStackRef tmp = GETLOCAL(oparg1);
+ GETLOCAL(oparg1) = value1;
DEAD(value1);
value2 = PyStackRef_DUP(GETLOCAL(oparg2));
+ PyStackRef_XCLOSE(tmp);
}
inst(STORE_FAST_STORE_FAST, (value2, value1 --)) {
uint32_t oparg1 = oparg >> 4;
uint32_t oparg2 = oparg & 15;
- SETLOCAL(oparg1, value1);
+ _PyStackRef tmp = GETLOCAL(oparg1);
+ GETLOCAL(oparg1) = value1;
DEAD(value1);
- SETLOCAL(oparg2, value2);
+ PyStackRef_XCLOSE(tmp);
+ tmp = GETLOCAL(oparg2);
+ GETLOCAL(oparg2) = value2;
DEAD(value2);
+ PyStackRef_XCLOSE(tmp);
}
pure inst(POP_TOP, (value --)) {
@@ -1775,7 +1782,9 @@ dummy_func(
);
ERROR_IF(1, error);
}
- SETLOCAL(oparg, PyStackRef_NULL);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = PyStackRef_NULL;
+ PyStackRef_XCLOSE(tmp);
}
inst(MAKE_CELL, (--)) {
@@ -1786,7 +1795,9 @@ dummy_func(
if (cell == NULL) {
ERROR_NO_POP();
}
- SETLOCAL(oparg, PyStackRef_FromPyObjectSteal(cell));
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = PyStackRef_FromPyObjectSteal(cell);
+ PyStackRef_XCLOSE(tmp);
}
inst(DELETE_DEREF, (--)) {
diff --git a/Python/ceval.c b/Python/ceval.c
index 11518684c136bd..4f628fdbabddbb 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -194,6 +194,7 @@ lltrace_instruction(_PyInterpreterFrame *frame,
}
fflush(stdout);
}
+
static void
lltrace_resume_frame(_PyInterpreterFrame *frame)
{
diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
index c2fc38f3c18e53..b6d9df32953892 100644
--- a/Python/ceval_macros.h
+++ b/Python/ceval_macros.h
@@ -221,15 +221,6 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#define LOCALS_ARRAY (frame->localsplus)
#define GETLOCAL(i) (frame->localsplus[i])
-/* The SETLOCAL() macro must not DECREF the local variable in-place and
- then store the new value; it must copy the old value to a temporary
- value, then store the new value, and then DECREF the temporary value.
- This is because it is possible that during the DECREF the frame is
- accessed by other code (e.g. a __del__ method or gc.collect()) and the
- variable would be pointing to already-freed memory. */
-#define SETLOCAL(i, value) do { _PyStackRef tmp = GETLOCAL(i); \
- GETLOCAL(i) = value; \
- PyStackRef_XCLOSE(tmp); } while (0)
#ifdef Py_STATS
#define UPDATE_MISS_STATS(INSTNAME) \
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 5b19ec182b5805..22d11059fcadb8 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -205,7 +205,6 @@
_PyStackRef value;
oparg = CURRENT_OPARG();
value = GETLOCAL(oparg);
- // do not use SETLOCAL here, it decrefs the old value
GETLOCAL(oparg) = PyStackRef_NULL;
stack_pointer[0] = value;
stack_pointer += 1;
@@ -307,9 +306,13 @@
oparg = 0;
assert(oparg == CURRENT_OPARG());
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -318,9 +321,13 @@
oparg = 1;
assert(oparg == CURRENT_OPARG());
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -329,9 +336,13 @@
oparg = 2;
assert(oparg == CURRENT_OPARG());
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -340,9 +351,13 @@
oparg = 3;
assert(oparg == CURRENT_OPARG());
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -351,9 +366,13 @@
oparg = 4;
assert(oparg == CURRENT_OPARG());
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -362,9 +381,13 @@
oparg = 5;
assert(oparg == CURRENT_OPARG());
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -373,9 +396,13 @@
oparg = 6;
assert(oparg == CURRENT_OPARG());
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -384,9 +411,13 @@
oparg = 7;
assert(oparg == CURRENT_OPARG());
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -394,9 +425,13 @@
_PyStackRef value;
oparg = CURRENT_OPARG();
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -2255,7 +2290,11 @@
stack_pointer = _PyFrame_GetStackPointer(frame);
JUMP_TO_ERROR();
}
- SETLOCAL(oparg, PyStackRef_NULL);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = PyStackRef_NULL;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -2268,7 +2307,11 @@
if (cell == NULL) {
JUMP_TO_ERROR();
}
- SETLOCAL(oparg, PyStackRef_FromPyObjectSteal(cell));
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = PyStackRef_FromPyObjectSteal(cell);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
break;
}
@@ -6314,7 +6357,9 @@
#endif
if (exit->executor && !exit->executor->vm_data.valid) {
exit->temperature = initial_temperature_backoff_counter();
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(exit->executor);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
}
if (exit->executor == NULL) {
_Py_BackoffCounter temperature = exit->temperature;
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 0bc92f30bfded2..5820147ff712a9 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -1082,7 +1082,9 @@
frame, this_instr, callable_o, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(res_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
}
}
}
@@ -1842,7 +1844,9 @@
frame, this_instr, func, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(result_o);
+ stack_pointer =
_PyFrame_GetStackPointer(frame);
}
}
}
@@ -2163,7 +2167,9 @@
frame, this_instr, callable_o, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(res_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
}
}
}
@@ -3837,7 +3843,11 @@
stack_pointer = _PyFrame_GetStackPointer(frame);
goto error;
}
- SETLOCAL(oparg, PyStackRef_NULL);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = PyStackRef_NULL;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH();
}
@@ -4781,7 +4791,9 @@
frame, this_instr, callable_o, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(res_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
}
}
}
@@ -4920,7 +4932,9 @@
frame, this_instr, func, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(result_o);
+ stack_pointer =
_PyFrame_GetStackPointer(frame);
}
}
}
@@ -5155,7 +5169,9 @@
frame, this_instr, callable_o, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(res_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
}
}
}
@@ -5421,7 +5437,9 @@
frame, this_instr, global_super, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(super);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
}
}
}
@@ -6858,7 +6876,6 @@
INSTRUCTION_STATS(LOAD_FAST_AND_CLEAR);
_PyStackRef value;
value = GETLOCAL(oparg);
- // do not use SETLOCAL here, it decrefs the old value
GETLOCAL(oparg) = PyStackRef_NULL;
stack_pointer[0] = value;
stack_pointer += 1;
@@ -7338,7 +7355,9 @@
frame, this_instr, global_super, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(super);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
}
}
}
@@ -7472,7 +7491,11 @@
if (cell == NULL) {
goto error;
}
- SETLOCAL(oparg, PyStackRef_FromPyObjectSteal(cell));
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = PyStackRef_FromPyObjectSteal(cell);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH();
}
@@ -8545,9 +8568,13 @@
INSTRUCTION_STATS(STORE_FAST);
_PyStackRef value;
value = stack_pointer[-1];
- SETLOCAL(oparg, value);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH();
}
@@ -8560,9 +8587,13 @@
value1 = stack_pointer[-1];
uint32_t oparg1 = oparg >> 4;
uint32_t oparg2 = oparg & 15;
- SETLOCAL(oparg1, value1);
+ _PyStackRef tmp = GETLOCAL(oparg1);
+ GETLOCAL(oparg1) = value1;
value2 = PyStackRef_DUP(GETLOCAL(oparg2));
stack_pointer[-1] = value2;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH();
}
@@ -8576,10 +8607,20 @@
value2 = stack_pointer[-2];
uint32_t oparg1 = oparg >> 4;
uint32_t oparg2 = oparg & 15;
- SETLOCAL(oparg1, value1);
- SETLOCAL(oparg2, value2);
- stack_pointer += -2;
+ _PyStackRef tmp = GETLOCAL(oparg1);
+ GETLOCAL(oparg1) = value1;
+ stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ tmp = GETLOCAL(oparg2);
+ GETLOCAL(oparg2) = value2;
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_XCLOSE(tmp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH();
}
diff --git a/Tools/cases_generator/analyzer.py
b/Tools/cases_generator/analyzer.py
index 724fba5f953a4e..11a559bca474b0 100644
--- a/Tools/cases_generator/analyzer.py
+++ b/Tools/cases_generator/analyzer.py
@@ -607,7 +607,6 @@ def has_error_without_pop(op: parser.CodeDef) -> bool:
"PyUnicode_GET_LENGTH",
"PyUnicode_READ_CHAR",
"Py_ARRAY_LENGTH",
- "Py_CLEAR",
"Py_FatalError",
"Py_INCREF",
"Py_IS_TYPE",
@@ -859,13 +858,7 @@ def compute_properties(op: parser.CodeDef) -> Properties:
)
error_with_pop = has_error_with_pop(op)
error_without_pop = has_error_without_pop(op)
- escapes = (
- bool(escaping_calls) or
- variable_used(op, "Py_DECREF") or
- variable_used(op, "Py_XDECREF") or
- variable_used(op, "Py_CLEAR") or
- variable_used(op, "SETLOCAL")
- )
+ escapes = bool(escaping_calls)
pure = False if isinstance(op, parser.LabelDef) else "pure" in
op.annotations
no_save_ip = False if isinstance(op, parser.LabelDef) else "no_save_ip" in
op.annotations
return Properties(
@@ -883,8 +876,7 @@ def compute_properties(op: parser.CodeDef) -> Properties:
stores_sp=variable_used(op, "SYNC_SP"),
uses_co_consts=variable_used(op, "FRAME_CO_CONSTS"),
uses_co_names=variable_used(op, "FRAME_CO_NAMES"),
- uses_locals=(variable_used(op, "GETLOCAL") or variable_used(op,
"SETLOCAL"))
- and not has_free,
+ uses_locals=variable_used(op, "GETLOCAL") and not has_free,
uses_opcode=variable_used(op, "opcode"),
has_free=has_free,
pure=pure,
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]