You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(py_class): remove __ffi_init_inplace__ to fix memory leak (#551)
## Summary
- **Fix memory leak** in `@py_class`: the custom `__new__` override
allocated a spurious C++ object via `__ffi_new__` whenever a py_class
instance was returned from C++, which was then orphaned when
`make_ret_object` overwrote `chandle` with the actual return value.
- **Remove `__ffi_init_inplace__`** entirely — both the C++
`MakeInitInplace` function, its registration, and the `kInitInplace`
constant.
- **Unify `c_class` and `py_class`** auto-generated `__init__` to both
use `self.__init_handle_by_constructor__(ffi_init, *args)`, differing
only in guard logic: py_class uses a `chandle != 0` guard (no-op when
already allocated), c_class uses a `type_info` identity guard
(`TypeError` from subclass).
- **Remove the custom `__new__` override** — no more spurious allocation
on the `make_ret` path.
- **Wrap user-defined `__init__`** on py_class with a `chandle == 0`
guard that pre-allocates via `__ffi_new__` before user code runs; use
`functools.wraps` to preserve metadata.
### Files changed
| File | Change |
|------|--------|
| `python/tvm_ffi/_dunder.py` | Core redesign: removed `inplace` param,
added `py_class_mode`, removed `__new__` override, added user-init
wrapping with `functools.wraps` |
| `python/tvm_ffi/registry.py` | Removed `inplace=False` kwarg from
`_make_init` call |
| `include/tvm/ffi/reflection/accessor.h` | Removed `kInitInplace`
constant |
| `include/tvm/ffi/reflection/registry.h` | Updated comments (removed
`__ffi_init_inplace__` references) |
| `src/ffi/extra/dataclass.cc` | Removed `MakeInitInplace()`, its
registration, `EnsureTypeAttrColumn` call |
| `python/tvm_ffi/dataclasses/py_class.py` | Updated comment |
| `tests/python/test_dataclass_init.py` | Removed `TestInitInplace`
class (5 tests) |
| `tests/python/test_dataclass_py_class.py` | Added 8 new tests in
`TestPyClassNoLeak` |
## Test plan
- [x] All 27 pre-commit linters pass
- [x] All 2103 Python tests pass (2095 existing + 8 new)
- [x] All 349 C++ tests pass
- [x] Memory leak validation: 20k construct+deepcopy cycles with no leak
0 commit comments