-
Notifications
You must be signed in to change notification settings - Fork 2
Changes made in sprint for PLDI deadline. #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Co-authored-by: xFrednet <xFrednet@gmail.com>
4b38c26 to
451886c
Compare
xFrednet
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are several loose ends, but all of them are pretty well documented in TODO comments.
Most of my comments are just thoughts, small additions and two TODO's for me :)
| #define MAXFREELIST(x) x | ||
| //#define MAXFREELIST(x) 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be part of the change set or is this an artifact of development/Debugging?
If this should be kept, it should be used for all _MAXFREELIST values in this file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found this useful for debugging memory safety issues with Asan. The freelists hide UAF and double-free that Asan would detect.
I think this is something that we could try to push into CPython for the sanitizer builds.
I am happy to drop from this PR. It isn't essential. I just would sooner not lose the code.
| // For immutable modules to find the mutable state and | ||
| // for logging purposes after md_dict is cleared | ||
| PyObject *md_name; | ||
| int md_frozen; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME: @xFrednet, Investigate if this field can be avoided with the change of the Module object type as part of the pre-freeze hook.
Include/refcount.h
Outdated
| PyAPI_FUNC(void) _Py_IncRef(PyObject *); | ||
| PyAPI_FUNC(void) _Py_DecRef(PyObject *); | ||
|
|
||
| // TODO(Immutable): Should this not be defined in the LIMITED_API? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe they need to be defined even with the LIMITED_API due to the dec and inc ref macros/functions being defined in the header. The leading _ should indicate that this function is still private and shouldn't be used directly
Objects/dictobject.c
Outdated
| if(!Py_CHECKWRITE(d)){ | ||
| PyErr_WriteToImmutable(d); | ||
| goto error; | ||
| return -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should NULL the result pointer, as this is the defined behaviour on fail AFAIK. This can also use goto error; which will NULL the result.
Now it looks like this logic is split across multiple functions, most often this one, but for this specific case, there is also a case in PyDict_SetDefault()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is probably a merging error. I will revert to the goto I think that fixes all the cases.
| #ifdef MERMAID_TRACING | ||
| #define TRACE_MERMAID_START() \ | ||
| do { \ | ||
| FILE* f = fopen("freeze_trace.md", "w"); \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Freeze calls can be nested due to reentry. will the cause problems, if the same file is opend and then closed twice? (Besides the output being no proper mermaid)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I think this is still useful. But perhaps needs more engineering. Should I drop from this PR, and make a separate PR for this?
| // CHANGES HERE NEED TO BE REFLECTED IN freeze_visit | ||
|
|
||
| if (PyType_Check(c)) { | ||
| // TODO(Immutable): mjp: Special case for types not sure if required. We should review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likely required until we have a custom tp_reachable function for Pyrona.
This will likely also cover parts of the special case for weak references, making all of this code way cleaner :D
| // as we didn't change anything. | ||
| PyObject* item = pop(state->visited_list); | ||
| _Py_CLEAR_IMMUTABLE(item); | ||
| // tp_clear all elements in the cycle. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment to explain why this is safe would be good :)
| // tp_clear all elements in the cycle. | |
| // tp_clear all elements in the cycle. | |
| // The elements will stay allocated since until `scc_return_to_gc` which will | |
| // decrement the RC by one |
| // // We need to add this attribute before traversing, so that if it creates a | ||
| // // dictionary, then this dictionary is frozen. | ||
| // if (state->freeze_location != NULL) { | ||
| // // Some objects don't have attributes that can be set. | ||
| // // As this is a Debug only feature, we could potentially increase the object | ||
| // // size to allow this to be stored directly on the object. | ||
| // if (PyObject_SetAttrString(obj, "__freeze_location__", state->freeze_location) < 0) { | ||
| // // Ignore failure to set _freeze_location | ||
| // PyErr_Clear(); | ||
| // // We still want to freeze the object, so we continue | ||
| // } | ||
| // } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not, that was due to a failure which I didn't understand. And never reinstated.
| if(!(tp->tp_getset == NULL || | ||
| tp->tp_getset == subtype_getsets_full || | ||
| tp->tp_getset == subtype_getsets_weakref_only || | ||
| tp->tp_getset == subtype_getsets_dict_only)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason for these changes? o.O
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Object was not tracked in the GC, so we don't need to merge it back. | ||
| _PyGCHead_SET_PREV(gc, NULL); | ||
| _PyGCHead_SET_NEXT(gc, NULL); | ||
| Returns true if the SCC's reference count has become zero. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function returns nothing, this comment is probably outdated?
38630f0 to
451886c
Compare
No description provided.