Skip to content

Commit

Permalink
refactor: use iteration to evaluate binary expressions (#6851)
Browse files Browse the repository at this point in the history
fix: init
  • Loading branch information
h-a-n-a authored Jun 18, 2024
1 parent b593043 commit c24c83f
Show file tree
Hide file tree
Showing 8 changed files with 4,992 additions and 46 deletions.
15 changes: 0 additions & 15 deletions crates/node_binding/src/env.rs

This file was deleted.

10 changes: 0 additions & 10 deletions crates/node_binding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ mod compiler;
mod panic;
mod plugins;

#[cfg(not(debug_assertions))]
mod env;

use plugins::*;
use rspack_binding_options::*;
use rspack_binding_values::*;
Expand Down Expand Up @@ -184,13 +181,6 @@ enum TraceState {

#[ctor]
fn init() {
#[cfg(not(debug_assertions))]
{
// 4mb stack size if not set
// For the case where its code has a lot of recursions, for example:
// https://github.com/highlightjs/highlight.js/blob/b9ae5fea90514b864f2c9b2889d7d3302d6156dc/src/languages/isbl.js#L21
env::set_env_if_unset("RUST_MIN_STACK", "4194304");
}
panic::install_panic_handler();
}

Expand Down
58 changes: 39 additions & 19 deletions crates/rspack_plugin_javascript/src/utils/eval/eval_binary_expr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use rspack_core::{DependencyLocation, SpanExt};
use swc_core::ecma::ast::{BinExpr, BinaryOp};
use swc_core::{
common::Spanned,
ecma::ast::{BinExpr, BinaryOp},
};

use crate::{utils::eval::BasicEvaluatedExpression, visitors::JavascriptParser};

Expand Down Expand Up @@ -74,11 +77,11 @@ fn is_always_different(a: Option<bool>, b: Option<bool>) -> bool {
#[inline]
fn handle_strict_equality_comparison(
eql: bool,
left: BasicEvaluatedExpression,
expr: &BinExpr,
scanner: &mut JavascriptParser,
) -> Option<BasicEvaluatedExpression> {
assert!(expr.op == BinaryOp::EqEqEq || expr.op == BinaryOp::NotEqEq);
let left = scanner.evaluate_expression(&expr.left);
let right = scanner.evaluate_expression(&expr.right);
let mut res = BasicEvaluatedExpression::with_range(expr.span.real_lo(), expr.span.hi().0);
let left_const = left.is_compile_time_value();
Expand Down Expand Up @@ -119,11 +122,11 @@ fn handle_strict_equality_comparison(
#[inline(always)]
fn handle_abstract_equality_comparison(
eql: bool,
left: BasicEvaluatedExpression,
expr: &BinExpr,
scanner: &mut JavascriptParser,
) -> Option<BasicEvaluatedExpression> {
assert!(expr.op == BinaryOp::EqEq || expr.op == BinaryOp::NotEq);
let left = scanner.evaluate_expression(&expr.left);
let right = scanner.evaluate_expression(&expr.right);
let mut res = BasicEvaluatedExpression::with_range(expr.span.real_lo(), expr.span.hi().0);

Expand All @@ -147,12 +150,11 @@ fn handle_abstract_equality_comparison(

#[inline(always)]
fn handle_logical_or(
left: BasicEvaluatedExpression,
expr: &BinExpr,
scanner: &mut JavascriptParser,
) -> Option<BasicEvaluatedExpression> {
let mut res = BasicEvaluatedExpression::with_range(expr.span.real_lo(), expr.span.hi().0);
let left = scanner.evaluate_expression(&expr.left);

match left.as_bool() {
Some(true) => {
// truthy || unknown = true
Expand Down Expand Up @@ -187,12 +189,11 @@ fn handle_logical_or(

#[inline(always)]
fn handle_logical_and(
left: BasicEvaluatedExpression,
expr: &BinExpr,
scanner: &mut JavascriptParser,
) -> Option<BasicEvaluatedExpression> {
let mut res = BasicEvaluatedExpression::with_range(expr.span.real_lo(), expr.span.hi().0);

let left = scanner.evaluate_expression(&expr.left);
match left.as_bool() {
Some(true) => {
// true && unknown = unknown
Expand Down Expand Up @@ -226,9 +227,12 @@ fn handle_logical_and(
}

#[inline(always)]
fn handle_add(expr: &BinExpr, scanner: &mut JavascriptParser) -> Option<BasicEvaluatedExpression> {
fn handle_add(
left: BasicEvaluatedExpression,
expr: &BinExpr,
scanner: &mut JavascriptParser,
) -> Option<BasicEvaluatedExpression> {
assert_eq!(expr.op, BinaryOp::Add);
let left = scanner.evaluate_expression(&expr.left);
let right = scanner.evaluate_expression(&expr.right);
let mut res = BasicEvaluatedExpression::with_range(expr.span.real_lo(), expr.span.hi.0);
if left.could_have_side_effects() || right.could_have_side_effects() {
Expand Down Expand Up @@ -376,21 +380,37 @@ fn handle_add(expr: &BinExpr, scanner: &mut JavascriptParser) -> Option<BasicEva
Some(res)
}

#[inline]
pub fn eval_binary_expression(
scanner: &mut JavascriptParser,
expr: &BinExpr,
) -> Option<BasicEvaluatedExpression> {
match expr.op {
BinaryOp::EqEq => handle_abstract_equality_comparison(true, expr, scanner),
BinaryOp::NotEq => handle_abstract_equality_comparison(false, expr, scanner),
BinaryOp::EqEqEq => handle_strict_equality_comparison(true, expr, scanner),
BinaryOp::NotEqEq => handle_strict_equality_comparison(false, expr, scanner),
BinaryOp::LogicalAnd => handle_logical_and(expr, scanner),
BinaryOp::LogicalOr => handle_logical_or(expr, scanner),
BinaryOp::Add => handle_add(expr, scanner),
_ => None,
let mut stack = vec![expr];
let mut expr = &*expr.left;
while let Some(bin) = expr.as_bin() {
stack.push(bin);
expr = &*bin.left;
}
let mut evaluated = None;
while let Some(expr) = stack.pop() {
let left = evaluated.unwrap_or_else(|| scanner.evaluate_expression(&expr.left));
evaluated = match expr.op {
BinaryOp::EqEq => handle_abstract_equality_comparison(true, left, expr, scanner),
BinaryOp::NotEq => handle_abstract_equality_comparison(false, left, expr, scanner),
BinaryOp::EqEqEq => handle_strict_equality_comparison(true, left, expr, scanner),
BinaryOp::NotEqEq => handle_strict_equality_comparison(false, left, expr, scanner),
BinaryOp::LogicalAnd => handle_logical_and(left, expr, scanner),
BinaryOp::LogicalOr => handle_logical_or(left, expr, scanner),
BinaryOp::Add => handle_add(left, expr, scanner),
_ => None,
}
.or_else(|| {
Some(BasicEvaluatedExpression::with_range(
expr.span().real_lo(),
expr.span_hi().0,
))
});
}
evaluated
}

fn join_locations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,6 @@ impl<'parser> JavascriptParser<'parser> {

// same as `JavascriptParser._initializeEvaluating` in webpack
// FIXME: should mv it to plugin(for example `parse.hooks.evaluate for`)
#[inline]
fn evaluating(&mut self, expr: &Expr) -> Option<BasicEvaluatedExpression> {
match expr {
Expr::Tpl(tpl) => eval::eval_tpl_expression(self, tpl),
Expand Down
Loading

2 comments on commit c24c83f

@rspack-bot
Copy link

Choose a reason for hiding this comment

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

📝 Benchmark detail: Open

Name Base (2024-06-18 553f785) Current Change
10000_development-mode + exec 2.21 s ± 22 ms 2.23 s ± 35 ms +0.94 %
10000_development-mode_hmr + exec 737 ms ± 12 ms 735 ms ± 13 ms -0.30 %
10000_production-mode + exec 2.57 s ± 22 ms 2.59 s ± 26 ms +1.01 %
arco-pro_development-mode + exec 1.94 s ± 68 ms 1.93 s ± 63 ms -0.52 %
arco-pro_development-mode_hmr + exec 441 ms ± 2.1 ms 443 ms ± 2.5 ms +0.27 %
arco-pro_production-mode + exec 3.53 s ± 85 ms 3.6 s ± 195 ms +2.03 %
threejs_development-mode_10x + exec 1.46 s ± 11 ms 1.47 s ± 18 ms +0.75 %
threejs_development-mode_10x_hmr + exec 799 ms ± 3.3 ms 789 ms ± 7.6 ms -1.22 %
threejs_production-mode_10x + exec 4.76 s ± 33 ms 4.79 s ± 26 ms +0.62 %

@rspack-bot
Copy link

Choose a reason for hiding this comment

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

📝 Ran ecosystem CI: Open

suite result
modernjs ❌ failure
_selftest ✅ success
nx ✅ success
rspress ✅ success
rsbuild ✅ success
compat ✅ success
examples ✅ success

Please sign in to comment.