| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| Expand Up | @@ -48,11 +48,13 @@ | |
| ) | ||
| from mypyc.common import TEMP_ATTR_NAME | ||
| from mypyc.ir.ops import ( | ||
| ERR_NEVER, | ||
| NAMESPACE_MODULE, | ||
| NO_TRACEBACK_LINE_NO, | ||
| Assign, | ||
| BasicBlock, | ||
| Branch, | ||
| Call, | ||
| InitStatic, | ||
| Integer, | ||
| LoadAddress, | ||
| Expand Down Expand Up | @@ -930,16 +932,41 @@ def emit_yield_from_or_await( | |
| to_yield_reg = Register(object_rprimitive) | ||
| received_reg = Register(object_rprimitive) | ||
|
|
||
| get_op = coro_op if is_await else iter_op | ||
| if isinstance(get_op, PrimitiveDescription): | ||
| iter_val = builder.primitive_op(get_op, [val], line) | ||
| helper_method = "__mypyc_generator_helper__" | ||
| if ( | ||
| isinstance(val, (Call, MethodCall)) | ||
| and isinstance(val.type, RInstance) | ||
| and val.type.class_ir.has_method(helper_method) | ||
| ): | ||
| # This is a generated native generator class, and we can use a fast path. | ||
| # This allows two optimizations: | ||
| # 1) No need to call CPy_GetCoro() or iter() since for native generators | ||
| # it just returns the generator object (implemented here). | ||
| # 2) Instead of calling next(), call generator helper method directly, | ||
| # since next() just calls __next__ which calls the helper method. | ||
| iter_val: Value = val | ||
|
Comment thread
Copy link
Copy Markdown
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityThe changes in this function implemented the bulk of the optimization.
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityMaybe add a bit more detailed comment (essentially summarizing the PR description) so we will not forget the motivation.
Sorry, something went wrong.
All reactions
|
||
| else: | ||
| iter_val = builder.call_c(get_op, [val], line) | ||
| get_op = coro_op if is_await else iter_op | ||
| if isinstance(get_op, PrimitiveDescription): | ||
| iter_val = builder.primitive_op(get_op, [val], line) | ||
| else: | ||
| iter_val = builder.call_c(get_op, [val], line) | ||
|
|
||
| iter_reg = builder.maybe_spill_assignable(iter_val) | ||
|
|
||
| stop_block, main_block, done_block = BasicBlock(), BasicBlock(), BasicBlock() | ||
| _y_init = builder.call_c(next_raw_op, [builder.read(iter_reg)], line) | ||
|
|
||
| if isinstance(iter_reg.type, RInstance) and iter_reg.type.class_ir.has_method(helper_method): | ||
| # Second fast path optimization: call helper directly (see also comment above). | ||
| obj = builder.read(iter_reg) | ||
| nn = builder.none_object() | ||
| m = MethodCall(obj, helper_method, [nn, nn, nn, nn], line) | ||
| # Generators have custom error handling, so disable normal error handling. | ||
| m.error_kind = ERR_NEVER | ||
| _y_init = builder.add(m) | ||
| else: | ||
| _y_init = builder.call_c(next_raw_op, [builder.read(iter_reg)], line) | ||
|
|
||
| builder.add(Branch(_y_init, stop_block, main_block, Branch.IS_ERROR)) | ||
|
|
||
| # Try extracting a return value from a StopIteration and return it. | ||
| Expand All | @@ -948,7 +975,7 @@ def emit_yield_from_or_await( | |
| builder.assign(result, builder.call_c(check_stop_op, [], line), line) | ||
| # Clear the spilled iterator/coroutine so that it will be freed. | ||
| # Otherwise, the freeing of the spilled register would likely be delayed. | ||
| err = builder.add(LoadErrorValue(object_rprimitive)) | ||
| err = builder.add(LoadErrorValue(iter_reg.type)) | ||
| builder.assign(iter_reg, err, line) | ||
| builder.goto(done_block) | ||
|
|
||
| Expand Down | ||
| Back | FazBrowse Home | New Git URL |
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.
Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityThis is the first part of the optimization.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.