-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
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
gh-121459: Deferred LOAD_ATTR (methods) #124101
base: main
Are you sure you want to change the base?
Conversation
Fidget-Spinner
commented
Sep 15, 2024
•
edited by bedevere-app
bot
Loading
edited by bedevere-app
bot
- Issue: PEP 703 Deferred reference counts #121459
_PyObject_TryGetInstanceAttributeStackRef(obj, name, method)) { | ||
if (!PyStackRef_IsNull(*method)) { | ||
PyStackRef_XCLOSE(descr_st); |
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 overwrites *method
, but not descr_st
, so descr_st
may store a stack reference that's not visible to the GC. That seems fragile and potentially a problem.
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 want to restore *method to descr_st
after this in some cases (see below). I guess the safe thing would be to convert it to a strong ref?
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 don't think you need both *method
and descr_st
if you refactor these function.
Alternatively take in a second _PyStackRef *
to store the temporary values in a place that is visible to the GC.
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 the second approach needs to wait for @mpage 's PR on adding an extra stack slot?
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.
Oh we don't, we can use self_or_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.
Ok nevermind, this does indeed need Matt's fix. Because we unconditionally write to self_or_null now.
@colesbury gentle ping to respond to the review comments please |
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 seems to add a lot of complexity.
LOAD_ATTR
is already the slow path, do you have performance numbers?
Without a significant speedup, this doesn't seem worth it.
For future reference, for large PRs like this, could you make sure there is specific issue where the change can be discussed and justified, rather adding them to a more general (and vague) issue like #121459
// This belongs here rather than pycore_stackref.h because including pycore_object.h | ||
// there causes a circular include. | ||
static inline _PyStackRef | ||
_Py_TryXGetStackRef(PyObject **ptr) |
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.
Please add clear comments as to what this does.
What is it "trying" to do? What happens if it fails? etc.
@@ -816,7 +834,8 @@ extern int _PyObject_StoreInstanceAttribute(PyObject *obj, | |||
PyObject *name, PyObject *value); | |||
extern bool _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, | |||
PyObject **attr); | |||
|
|||
extern bool _PyObject_TryGetInstanceAttributeStackRef(PyObject *obj, PyObject *name, |
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.
Likewise. Anything with "try" in the name needs to be carefully documented.
@@ -863,6 +882,7 @@ PyAPI_FUNC(PyObject*) _PyObject_LookupSpecialMethod(PyObject *self, PyObject *at | |||
extern int _PyObject_IsAbstract(PyObject *); | |||
|
|||
PyAPI_FUNC(int) _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); | |||
PyAPI_FUNC(int) _PyObject_GetMethodStackRef(PyObject *obj, PyObject *name, _PyStackRef *method, _PyStackRef *spare); |
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.
Why does this have a "spare" parameter?
@@ -900,6 +920,8 @@ PyAPI_DATA(int) _Py_SwappedOp[]; | |||
|
|||
extern void _Py_GetConstant_Init(void); | |||
|
|||
extern void _PyType_LookupStackRef(PyTypeObject *type, PyObject *name, _PyStackRef *result); |
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.
Can't this fail? It should probably return an int
indicating success/failure/error.
@@ -2054,20 +2054,19 @@ dummy_func( | |||
#endif /* ENABLE_SPECIALIZATION */ | |||
} | |||
|
|||
op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) { | |||
op(_LOAD_ATTR, (owner -- attr[1], self_or_null[1] if (oparg & 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.
op(_LOAD_ATTR, (owner -- attr[1], self_or_null[1] if (oparg & 1))) { | |
op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) { |
You don't need the arrays. The code generator should spill the values to the in-memory stack if necessary.
@@ -1335,6 +1335,11 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache, | |||
goto error; | |||
} | |||
|
|||
/* Reserve an extra word on the stack to ensure there is space for uops to |
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.
Why is this necessary?
@markshannon I'm tempted to wait for Matt to land his LOAD_ATTR specialization PR then take a look again. It may be possible that specialization makes this PR less useful. |