The GitHub Actions job "CI" on tvm-ffi.git/pyobject has failed. Run started by GitHub user cyx-6 (triggered by cyx-6).
Head commit for run: 1bdf1827192cb20d9719894212d6adea42b5e6e1 / Yaxing Cai <[email protected]> [FEAT][Python] Tie Python wrapper lifetime to underlying C++ FFI object Make ``a.x is a.x`` and ``id(a.x)`` stable in Python by attaching every Python wrapper to its underlying C++ object via a 32-byte ``PyCustomizeAllocHeader`` prepended to every Object allocation. Reported by Junru Shao as the largest source of agent / OAI-monorepo migration failures. Implements the design in Tianqi Chen's "PyObjectTying" doc (2026-05-01). The header has a three-state machine: (a) py_obj == NULL && cached_mem == NULL : never wrapped on Python side (b) py_obj != NULL && cached_mem != NULL : live Python wrapper (c) py_obj == NULL && cached_mem != NULL : wrapper finalized, mem cached State (b) gives stable identity while the wrapper is alive. State (c) preserves the wrapper memory across a Python finalize so a later attribute access on a still-live C++ object reuses the same address. Implementation notes: - ``SimpleObjAllocator`` (memory.h) and the three Python-class bypass sites in ``src/ffi/extra/dataclass.cc`` now allocate ``kPyHeaderOffset + sizeof(T)`` bytes and zero-initialize the prepended header. The C++ deleter's Weak branch calls ``free_cb(cached_mem)`` if set, then frees the whole block. - Cython's ``def __del__`` on ``CObject`` is mapped to ``tp_finalize`` (PEP 442) by ``-DCYTHON_USE_TP_FINALIZE=1``. Cython 3.x disables this under ``USE_SABI`` because ``PyObject_CallFinalizerFromDealloc`` was added to the limited API only in 3.13; a 16-line shim in ``tvm_ffi_python_helpers.h`` reimplements it from limited-ABI primitives (``PyType_GetSlot``, ``Py_SET_REFCNT``, ``Py_REFCNT``). - Caching is opt-in per call site. ``FieldGetter`` (attribute access) uses ``cache_lookup=True``. FFI return values, callback arg unpacking, and rvalue-ref paths use ``make_ret_object_no_cache`` to preserve the classical "fresh wrapper per FFI return" semantics that ``_move()`` and tests like ``test_rvalue_ref`` rely on. - ``TVMFFIPyArgSetterObjectRValueRef_`` eagerly clears the source's header binding before the C++ side nulls its ``chandle``; otherwise the deleter would later call ``PyObject_GC_Del`` on a still-live Python wrapper. - ``PyNativeObject`` types (``String``, ``Bytes``) bypass the binding — they discard the transient ``Object`` wrapper after construction and do not need identity stability. Tests: full Python suite passes; new ``tests/python/test_pyobject_tying.py`` covers state-(b) identity, state-(c) revive (including a 2000-cycle single-address invariant), pickle round-trip, RValueRef move regression, type-mismatch fallthrough, mutable-field replacement, and the PyNativeObject exemption. Report URL: https://github.com/apache/tvm-ffi/actions/runs/26091613451 With regards, GitHub Actions via GitBox --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
