From e26916ceaeb5af95d87cb7da30a66d99dacdc9ff Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:53:28 +0000 Subject: [PATCH] perf(transformer/optional-chaining): mark `enter_expression` as inline (#7390) --- .../src/es2020/optional_chaining.rs | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/crates/oxc_transformer/src/es2020/optional_chaining.rs b/crates/oxc_transformer/src/es2020/optional_chaining.rs index 725b30a53614e..ae092c080ca37 100644 --- a/crates/oxc_transformer/src/es2020/optional_chaining.rs +++ b/crates/oxc_transformer/src/es2020/optional_chaining.rs @@ -90,32 +90,18 @@ impl<'a, 'ctx> OptionalChaining<'a, 'ctx> { } impl<'a, 'ctx> Traverse<'a> for OptionalChaining<'a, 'ctx> { + // `#[inline]` because this is a hot path + #[inline] fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { - *expr = match expr { - Expression::ChainExpression(_) => { - if self.is_inside_function_parameter { - // To insert the temp binding in the correct scope, we wrap the expression with - // an arrow function. During the chain expression transformation, the temp binding - // will be inserted into the arrow function's body. - Self::wrap_arrow_function(expr, ctx) - } else { - self.transform_chain_expression(false, expr, ctx) - } - } + match expr { + Expression::ChainExpression(_) => self.transform_chain_expression(expr, ctx), Expression::UnaryExpression(unary_expr) - if unary_expr.operator == UnaryOperator::Delete => + if unary_expr.operator == UnaryOperator::Delete + && matches!(unary_expr.argument, Expression::ChainExpression(_)) => { - let Expression::ChainExpression(_) = unary_expr.argument else { - return; - }; - if self.is_inside_function_parameter { - // Same as the above explanation - Self::wrap_arrow_function(expr, ctx) - } else { - self.transform_chain_expression(true, &mut unary_expr.argument, ctx) - } + self.transform_update_expression(expr, ctx); } - _ => return, + _ => (), }; } @@ -331,12 +317,41 @@ impl<'a, 'ctx> OptionalChaining<'a, 'ctx> { ctx.ast.expression_assignment(SPAN, AssignmentOperator::Assign, left, right) } + /// Transform chain expression + fn transform_chain_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { + *expr = if self.is_inside_function_parameter { + // To insert the temp binding in the correct scope, we wrap the expression with + // an arrow function. During the chain expression transformation, the temp binding + // will be inserted into the arrow function's body. + Self::wrap_arrow_function(expr, ctx) + } else { + self.transform_chain_expression_impl(false, expr, ctx) + } + } + + /// Transform update expression + fn transform_update_expression( + &mut self, + expr: &mut Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + *expr = if self.is_inside_function_parameter { + // Same as the above `transform_chain_expression` explanation + Self::wrap_arrow_function(expr, ctx) + } else { + // Unfortunately no way to get compiler to see that this branch is provably unreachable. + // We don't want to inline this function, to keep `enter_expression` as small as possible. + let Expression::UnaryExpression(unary_expr) = expr else { unreachable!() }; + self.transform_chain_expression_impl(true, &mut unary_expr.argument, ctx) + } + } + /// Transform chain expression to conditional expression which contains a lot of checks /// /// This is the root transform function for chain expressions. It calls /// [`Self::transform_chain_element_recursion`] to transform the chain expression elements, /// and then joins the transformed elements with the conditional expression. - fn transform_chain_expression( + fn transform_chain_expression_impl( &mut self, is_delete: bool, chain_expr: &mut Expression<'a>,