Expand out SETLOCAL so that code generator can see the decref. Mark Py_CLEAR as escaping
inst(LOAD_FAST_AND_CLEAR, (-- value)) {
value = GETLOCAL(oparg);
- // do not use SETLOCAL here, it decrefs the old value
GETLOCAL(oparg) = PyStackRef_NULL;
}
}
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 --)) = {
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 --)) {
);
ERROR_IF(1, error);
}
- SETLOCAL(oparg, PyStackRef_NULL);
+ _PyStackRef tmp = GETLOCAL(oparg);
+ GETLOCAL(oparg) = PyStackRef_NULL;
+ PyStackRef_XCLOSE(tmp);
}
inst(MAKE_CELL, (--)) {
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, (--)) {
}
fflush(stdout);
}
+
static void
lltrace_resume_frame(_PyInterpreterFrame *frame)
{
#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) \
_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;
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
_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;
}
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;
}
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;
}
#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;
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);
}
}
}
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);
}
}
}
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);
}
}
}
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();
}
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);
}
}
}
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);
}
}
}
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);
}
}
}
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);
}
}
}
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;
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);
}
}
}
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();
}
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();
}
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();
}
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();
}
"PyUnicode_GET_LENGTH",
"PyUnicode_READ_CHAR",
"Py_ARRAY_LENGTH",
- "Py_CLEAR",
"Py_FatalError",
"Py_INCREF",
"Py_IS_TYPE",
)
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(
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,