Skip to content

perf(lowering): avoid cloning concrete enum variants in extern lowering#9836

Open
VolodymyrBg wants to merge 1 commit intostarkware-libs:mainfrom
VolodymyrBg:perf/lowering-extern-enum-variants-iter
Open

perf(lowering): avoid cloning concrete enum variants in extern lowering#9836
VolodymyrBg wants to merge 1 commit intostarkware-libs:mainfrom
VolodymyrBg:perf/lowering-extern-enum-variants-iter

Conversation

@VolodymyrBg
Copy link
Copy Markdown
Contributor

Summary

Replaced the cloned iteration with iter().copied() and preallocated arm_var_ids using Vec::with_capacity(concrete_variants.len()). Behavior is unchanged; this is a small performance cleanup that removes redundant work.


Type of change

  • Performance improvement

Why is this change needed?

LoweredExprExternEnum::as_var_usage cloned the whole concrete_variants vector before iteration (clone().into_iter()), even though the elements are Copy and only read access is needed. This introduced unnecessary allocation and copying on every extern-enum lowering path.

@reviewable-StarkWare
Copy link
Copy Markdown

This change is Reviewable

Copy link
Copy Markdown
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi reviewed all commit messages and made 1 comment.
Reviewable status: 0 of 1 files reviewed, 1 unresolved discussion (waiting on VolodymyrBg).


crates/cairo-lang-lowering/src/lower/context.rs line 395 at r1 (raw file):

                .add(ctx, &mut subscope.statements);
                Ok((subscope.goto_callsite(Some(result)), block_id))
            })

Suggestion:

        let (sealed_blocks, block_ids, arm_var_ids): (Vec<_>, Vec<_>, Vec<_>) = concrete_variants
            .clone()
            .into_iter()
            .iter()
            .copied()
            .map(|concrete_variant| {
                let mut subscope = builder.child_block_builder(ctx.blocks.alloc_empty());
                let block_id = subscope.block_id;

                let mut var_ids = Vec::with_capacity(self.ref_args.len());
                // Bind the ref parameters.
                for ref_arg in &self.ref_args {
                    let var = ctx.new_var(VarRequest { ty: ref_arg.ty(), location: self.location });
                    var_ids.push(var);
                    if let RefArg::Ref(member_path) = ref_arg {
                        subscope.update_ref(ctx, member_path, var);
                    }
                }

                let before_returns = var_ids.len();
                var_ids.extend(
                    extern_facade_return_tys(ctx.db, &concrete_variant.ty)
                        .iter()
                        .map(|ty| ctx.new_var(VarRequest { ty: *ty, location: self.location })),
                );
                let returns = var_ids[before_returns..].iter().copied();
                let maybe_input =
                    extern_facade_expr(ctx, concrete_variant.ty, returns, self.location)
                        .as_var_usage(ctx, &mut subscope);
                let input = match maybe_input {
                    Ok(var_usage) => var_usage,
                    Err(err) => {
                        return handle_lowering_flow_error(ctx, subscope, err)
                            .map(|_| (None, block_id));
                    }
                };
                let result = generators::EnumConstruct {
                    input,
                    variant: concrete_variant,
                    location: self.location,
                }
                .add(ctx, &mut subscope.statements);
                Ok((subscope.goto_callsite(Some(result)), block_id, var_ids))
            })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants