Le dim. 5 avr. 2020 à 23:07, Skip Montanaro firstname.lastname@example.org a écrit :
I'm trying it the simplest way I can think of. Registers are exactly like local variables, so SETLOCAL Py_XDECREFs whatever is already there before overwriting it with a new value. At the end of _PyEval_EvalFrameDefault if the code object's co_flags includes the (new) CO_REGISTER flag, it loops over the stack/register space calling Py_CLEAR. The stack/register space is also Py_CLEAR'd when the frame is first allocated.
Let's say that you call "func()". The stack-based bytecode "LOAD_GLOAL 0; CALL_FUNC 0" becomes register-based bytecode "LOAD_GLOBAL_REG %r1, 0; CALL_FUNC_REG %r2, %r1": the function result is stored into %r2 register.
The problem is that if the %r2 is not cleared explicitly, you change the object lifetime and so the Python semantics. The register %r2 must be cleared explicitly.
Same issue applies for %r1 (which stores a global variable).
The correct code should be "LOAD_GLOBAL_REG %r1, 0; CALL_FUNC_REG %r2, %r1; CLEAR_REG %r1; CLEAR_REG %r2".
A compiler can optimize it to: "LOAD_GLOBAL_REG %r1, 0; CALL_FUNC_REG %r1, %r1; CLEAR_REG %r1" (remove %r2: reuse %r1).
For example, I expect to get immediately a ResourceWarning when running the following script demo.py with python3 -Wd demo.py: --- import time
def func(): open("/etc/issue")
func() # ResourceWarning expected here time.sleep(60) ---