Conversation
xFrednet
left a comment
There was a problem hiding this comment.
The addition itself looks good, but it doesn't set the tp_reachable for most built-in types. Once that is done it should be good to go.
Sounds good. I mostly wanted to get someone else's eyes on it, and then we can decide how broad a blast radius we want. |
| if (co->_co_cached != NULL) { | ||
| Py_VISIT(co->_co_cached->_co_code); | ||
| Py_VISIT(co->_co_cached->_co_varnames); | ||
| Py_VISIT(co->_co_cached->_co_cellvars); | ||
| Py_VISIT(co->_co_cached->_co_freevars); | ||
| } |
There was a problem hiding this comment.
This makes me worry about write barriers on the cache. There is a lot of stuff around modifying this for NoGIL
Objects/typeobject.c
Outdated
| /* | ||
| * TODO: We should discuss this. I am a little confused about the | ||
| * correct way to do this. This gives a good level of compatibility, | ||
| * but is perhaps too much. | ||
| * |
Objects/dictobject.c
Outdated
| static int | ||
| dict_reachable(PyObject *op, visitproc visit, void *arg) |
There was a problem hiding this comment.
NIT: When I implemented this, I used a dict_visit function with a flag to indicate it the keys should be used or not:
Lines 4975 to 5025 in e6fe674
I think that's slightly cleaner than having two mostly identical visit functions, but this is a style thing and this is good to go as is.
Objects/exceptions.c
Outdated
| .tp_reachable = BaseException_reachable, | ||
| 0, /* tp_weaklistoffset */ | ||
| 0, /* tp_iter */ | ||
| 0, /* tp_iternext */ | ||
| BaseException_methods, /* tp_methods */ | ||
| BaseException_members, /* tp_members */ | ||
| BaseException_getset, /* tp_getset */ | ||
| 0, /* tp_base */ | ||
| 0, /* tp_dict */ | ||
| 0, /* tp_descr_get */ | ||
| 0, /* tp_descr_set */ | ||
| offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */ | ||
| BaseException_init, /* tp_init */ | ||
| 0, /* tp_alloc */ | ||
| BaseException_new, /* tp_new */ | ||
| .tp_vectorcall = BaseException_vectorcall, |
There was a problem hiding this comment.
This seems weird, why does the change add all of these? Shouldn't it just be
.tp_reachable = BaseException_reachable,
xFrednet
left a comment
There was a problem hiding this comment.
Good changes, mostly high level comments
| Py_VISIT(lookup_tp_bases(type)); | ||
| Py_VISIT(type->tp_base); | ||
|
|
||
| /* Do NOT visit tp_subclasses or tp_weaklist here. |
There was a problem hiding this comment.
Funny how we talked about tp_weaklist earlier today ^^
There was a problem hiding this comment.
Yeah, my memory of what I think we do, and what we do is not consistent anymore
| static int | ||
| paramspecattr_reachable(PyObject *self, visitproc visit, void *arg) | ||
| { | ||
| Py_VISIT(_PyObject_CAST(Py_TYPE(self))); | ||
| return paramspecattr_traverse(self, visit, arg); | ||
| } |
There was a problem hiding this comment.
Why do types created via typeslots need a custom tp_reachable implementation? Shouldn't these types visit the type anyways?
I hoped that we could just reuse the tp_traverse for these.
There was a problem hiding this comment.
Not sure. Should the typeslots have to have it? There are a lot of things already created by typeslots, and we don't want them to magically get a tp_reachable without some thought?
There was a problem hiding this comment.
Sorry, I mean that most types that already implement tp_traverse should be able to say .tp_reachable = my_traverse and be good to go. AFAIK objects with heap types are supposed to visit them in tp_traverse
Python/immutability.c
Outdated
| PySys_FormatStderr( | ||
| "freeze: type '%.100s' has no tp_traverse and no tp_reachable\n", | ||
| tp->tp_name); |
There was a problem hiding this comment.
This feels like it should only be printed in debug builds?
Thinking about it, each freezable type should have a tp_reachable since it at least needs to reference the type. So maybe add an explanation comment and then leave the message.
There was a problem hiding this comment.
Guess it depends on whether we are just trying to run stuff and see what happens?
There was a problem hiding this comment.
For the current state of the implementation, it's probably correct to log this, so let's keep it as is for now.
| static PyModuleDef_Slot _test_reachable_slots[] = { | ||
| {Py_mod_exec, _test_reachable_exec}, | ||
| {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | ||
| {Py_mod_gil, Py_MOD_GIL_NOT_USED}, |
There was a problem hiding this comment.
We probably want a Py_mod_reachable as well. But I think this should be done in a follow-up PR. I also need to hack on modules again, so I can take over the addition of that.
|
The The ASAN may be also on immutable main. At least I also got an ASan error: ASAN error |
Co-authored-by: Fridtjof Stoldt <xFrednet@gmail.com>
📚 Documentation preview 📚: https://cpython-previews--65.org.readthedocs.build/