Skip to content

reference leak when a JIT trace is rewound #157875

Description

@johng

Bug report

Bug description:

import gc
import sys
import weakref

def run():
    class C:
        def __iter__(self):
            return self
        def __next__(self):
            raise StopIteration

    obj = C()
    for _ in range(10_000):
        for _ in obj:
            pass
    return weakref.ref(C)


ref = run()
gc.collect()
print("jit enabled:", sys._jit.is_enabled())
print("leaked:", ref() is not None)

This looks to be caused by value-recording uop (in the RECORD family) taking a strong reference to an object not being decref'd when traces are rewound

{
            _PyUOpInstruction *curr = uop_buffer_last(trace);
            while (curr->opcode != _SET_IP && uop_buffer_length(trace) > 2) {
                trace->next--;
                curr = uop_buffer_last(trace);
            }
            if (curr->opcode == _SET_IP) {
                int32_t old_target = (int32_t)uop_get_target(curr);
                curr->opcode = _DEOPT;
                curr->format = UOP_FORMAT_TARGET;
                curr->target = old_target;
            }
            goto done;
        }

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)topic-JITtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions