-
-
Notifications
You must be signed in to change notification settings - Fork 34k
gh-143414: Implement unique reference tracking for JIT, optimize unpacking of such tuples #144300
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
base: main
Are you sure you want to change the base?
gh-143414: Implement unique reference tracking for JIT, optimize unpacking of such tuples #144300
Conversation
|
Discussed with @Fidget-Spinner, will reopen the PR after implementing |
|
Windows Ci failure looks possibly related, can you please look into it? |
Fidget-Spinner
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.
This is excellent. Just 2 comments, then I think it's safe to merge.
|
|
||
| op(_COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) { | ||
| assert(oparg > 0); | ||
| bottom = PyJitRef_IsUnique(bottom) ? PyJitRef_StripReferenceInfo(bottom) : bottom; |
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.
We only need to strip unique info here, not the borrow info too. This way we still get refcount elimination with the borrow.
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 consistent with the code?
If the ref is unique, we remove the unique tag, otherwise we leave it as is. Since a ref cannot be both unique and borrowed at the same time, borrowed/invalid refs will be maintained.
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.
Sounds good, thanks!
markshannon
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.
We need to be very careful about tracking the uniqueness of a reference.
Uniqueness of a reference is a property of the whole VM, if we miss any operation that can duplicate a reference, we could introduce a serious bug.
With that in mind, I'd recommend only tracking references that remain on the stack, as it is too easy to make new references to objects stored in local variables:
- Through away the uniqueness in
STORE_FAST - Assert that references are not unique in
LOAD_FAST[_BORROW]
Other than that, I think the analysis is sound.
This could be considerable more efficient, see comments below:
| DECREF_INPUTS(); | ||
| } | ||
|
|
||
| op(_UNPACK_SEQUENCE_UNIQUE_TUPLE, (seq -- values[oparg])) { |
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 is might end up being less efficient than _UNPACK_SEQUENCE_TWO_TUPLE due to the looping and having to spill the values to memory.
I think it is worth making two variants of this for 2 and 3 length tuples.
| PyObject **items = _PyTuple_ITEMS(seq_o); | ||
| for (int i = oparg; --i >= 0; ) { | ||
| *values++ = PyStackRef_FromPyObjectSteal(items[i]); | ||
| items[i] = NULL; |
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.
If we free the tuple directly, we don't need to NULL out the fields.
| PyObject *seq_o = PyStackRef_AsPyObjectBorrow(seq); | ||
| assert(PyTuple_CheckExact(seq_o)); | ||
| assert(PyTuple_GET_SIZE(seq_o) == oparg); | ||
| DEOPT_IF(!_PyObject_IsUniquelyReferenced(seq_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.
| DEOPT_IF(!_PyObject_IsUniquelyReferenced(seq_o)); | |
| assert(_PyObject_IsUniquelyReferenced(seq_o)); |
If our analysis is correct, we don't need a runtime check.
| *values++ = PyStackRef_FromPyObjectSteal(items[i]); | ||
| items[i] = NULL; | ||
| } | ||
| PyStackRef_CLOSE_SPECIALIZED(seq, _PyTuple_EmptyExactDealloc); |
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.
| PyStackRef_CLOSE_SPECIALIZED(seq, _PyTuple_EmptyExactDealloc); | |
| PyObject_GC_UnTrack(seq_o); | |
| _PyTuple_Free(seq_o); |
| /* Methods */ | ||
|
|
||
| void | ||
| _PyTuple_EmptyExactDealloc(PyObject *obj) |
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.
Rather than a deallocing the tuple, we just need to free it.
Something like _PyTuple_Free.
Just assert that Py_SIZE(op) != 0 and free the tuple.
| } | ||
|
|
||
| op(_UNPACK_SEQUENCE_UNIQUE_TUPLE, (seq -- values[oparg])) { | ||
| PyObject *seq_o = PyStackRef_AsPyObjectBorrow(seq); |
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.
| PyObject *seq_o = PyStackRef_AsPyObjectBorrow(seq); | |
| PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); |
We want to free the tuple directly, so we need to steal the reference.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase And if you don't make the requested changes, you will be put in the comfy chair! |
Some notes:
_BUILD_TUPLE, to be extended to other objects in the future_LOAD_FAST_*and_COPY.Would appreciate any feedback.
Thanks
unique reference trackingin Tier 2 for reference count optimizations #143414