| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
| self.assertIn("_BUILD_TUPLE", uops) | ||
| self.assertIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops) |
There was a problem hiding this comment.
_BUILD_TUPLE is preventing us from optimizing out _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW.
The bytecode is basically:
LOAD_CONST
LOAD_CONST
_BUILD_TUPLE
_POP_CALL_TWO_LOAD_CONST_INLINE_BORROWTo optimize this, we'd need some special handling for _BUILD_TUPLE in remove_unneeded_uops.
Sorry, something went wrong.
There was a problem hiding this comment.
Got it, might be worth looking into next if you're up for it! Could be tricky, though.
Sorry, something went wrong.
|
When you're done making the requested changes, leave the comment: I have made the requested changes; please review again. |
Sorry, something went wrong.
So that was a lie 😆 Anyway, I think I addressed all your comments! :) I have made the requested changes; please review again |
Sorry, something went wrong.
|
Thanks for making the requested changes! @brandtbucher: please review the changes made to this pull request. |
Sorry, something went wrong.
There was a problem hiding this comment.
Looks good, just a few suggestions:
Sorry, something went wrong.
| self.assertIn("_BUILD_TUPLE", uops) | ||
| self.assertIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops) |
There was a problem hiding this comment.
Got it, might be worth looking into next if you're up for it! Could be tricky, though.
Sorry, something went wrong.
| for _ in range(n): | ||
| # One of the classes is unknown, so we can't narrow | ||
| # to True or False, only bool | ||
| y = isinstance(42, (eval('str'), int)) |
There was a problem hiding this comment.
I'm confused, why can't we narrow to True? We can't remove the call, but the result is known.
Sorry, something went wrong.
There was a problem hiding this comment.
Yep, that was a brainfart 😄 I somehow conflated narrowing to True/False with replacing the op, but we can obviously just narrow without removing the call as you said!
Sorry, something went wrong.
| def testfunc(n): | ||
| x = 0 | ||
| for _ in range(n): | ||
| y = isinstance(42, ()) |
There was a problem hiding this comment.
I had to pause and think for a second to figure out what this would even do. Nice edge case.
Sorry, something went wrong.
| // It could potentially define its own __instancecheck__ | ||
| // method so we can only deduce bool. | ||
| out = NULL; | ||
| break; |
There was a problem hiding this comment.
Could this be continue? We could still narrow to True later to handle cases like the one I called out above, right?
| break; | |
| continue; |
Sorry, something went wrong.
There was a problem hiding this comment.
Yup, see #134543 (comment). I just needed to add some extra bookkeeping to know when we can replace the call and when not.
Sorry, something went wrong.
| } | ||
| PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, item); | ||
| if (cls_o && | ||
| sym_matches_type(item, &PyType_Type) && |
There was a problem hiding this comment.
Maybe add a comment explaining that this is to protect against metaclasses definine __instancecheck__.
Sorry, something went wrong.
There was a problem hiding this comment.
How would you formulate it? I don't think of it as specifically a guard for __instancecheck__ but basically PyObject_TypeCheck adapted to the JIT optimizer.
Sorry, something went wrong.
There was a problem hiding this comment.
We're not only checking that the object is a subclass of type, we're also checking that it is an exact instance of type itself. We care about this second condition because it guarantees that __instancecheck__ doesn't exist (otherwise we would need to look it up to check if it exists or not).
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks for the clarification, I added a comment :)
Sorry, something went wrong.
|
Off-topic, but something I've been thinking about that you may want to check out next: removing bounds checks when indexing into strings and tuples with a constant index. |
Sorry, something went wrong.
|
Thanks for the review! Super helpful as always :) I'll leave this open for a few days so @Fidget-Spinner can also have a look :)
Sure, I can look into that! I guess this will also require knowing the string/tuple length? |
Sorry, something went wrong.
| if (cls_o && | ||
| // Ensure that item is an exact instance of `type` ensuring that | ||
| // there is no __instancecheck__ defined. | ||
| sym_matches_type(item, &PyType_Type) && |
There was a problem hiding this comment.
Wait, wouldn't this only work on something that is isinstance(x, type), like the actual type itself, not any type like int? Sorry, I'm confused!
Sorry, something went wrong.
There was a problem hiding this comment.
Hmm I don't believe so. If item is e.g. int then sym_matches_type(item, &PyType_Type) should return true
Sorry, something went wrong.
There was a problem hiding this comment.
For example something like this seems to work:
JitOptRef ref_type = _Py_uop_sym_new_const(ctx, (PyObject *)&PyLong_Type);
TEST_PREDICATE(_Py_uop_sym_matches_type(ref_type, &PyType_Type), "int is not a type");
Sorry, something went wrong.
There was a problem hiding this comment.
That''s kinda strange. The code for _Py_uop_sym_matches_type is:
_Py_uop_sym_get_type(sym) == typ
so it's a pointer comparison, not a subclass check.
Sorry, something went wrong.
There was a problem hiding this comment.
The subclass check is done after with PyType_IsSubtype if that's what you mean? The current version of _CALL_ISINSTANCE (which does not handle tuples) works the same way though. @brandtbucher, what do you think?
Sorry, something went wrong.
|
I'm really sorry Tomas, but the more I look at the code, the more I feel the complexity is not worth it in this case. __instancecheck__ is tricky (and you've handled that well in the code), but I feel for the additional lines we get in the optimizer_bytecodes.c, we don't get much back in terms of optimization :(. |
Sorry, something went wrong.
There was a problem hiding this comment.
We need a test for a type with __instancecheck__, otherwise it LGTM, and you can merge after the test is added
Sorry, something went wrong.
|
This PR is stale because it has been open for 30 days with no activity. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
We can already const eval isinstance(inst, cls) calls when both arguments are known, but only if cls is a single class (e.g. int).
This PR adds support for isinstance(inst, (cls1, cls2, ..., clsN)). This allows us to optimize for example:
We can narrow to True even when only some of the classes are known, as long as inst is an instance of one of the known classes.