Skip to content

Commit f3f6012

Browse files
authored
refactor(ecmascript): avoid redundant checks by splitting up match arms (#12782)
Makes code a lot easier to understand and avoids some redundant checks in runtime.
1 parent 3f37ed1 commit f3f6012

File tree

1 file changed

+87
-79
lines changed
  • crates/oxc_ecmascript/src/constant_evaluation

1 file changed

+87
-79
lines changed

crates/oxc_ecmascript/src/constant_evaluation/mod.rs

Lines changed: 87 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -233,51 +233,60 @@ fn binary_operation_evaluate_value_to<'a>(
233233
}
234234
None
235235
}
236-
BinaryOperator::Subtraction
237-
| BinaryOperator::Division
238-
| BinaryOperator::Remainder
239-
| BinaryOperator::Multiplication
240-
| BinaryOperator::Exponential => {
236+
BinaryOperator::Subtraction => {
241237
let lval = left.evaluate_value_to_number(ctx)?;
242238
let rval = right.evaluate_value_to_number(ctx)?;
243-
let val = match operator {
244-
BinaryOperator::Subtraction => lval - rval,
245-
BinaryOperator::Division => lval / rval,
246-
BinaryOperator::Remainder => {
247-
if rval.is_zero() {
248-
f64::NAN
249-
} else {
250-
lval % rval
251-
}
252-
}
253-
BinaryOperator::Multiplication => lval * rval,
254-
BinaryOperator::Exponential => {
255-
let result = lval.powf(rval);
256-
// For now, ignore the result if it large or has a decimal part
257-
// so that the output does not become bigger than the input.
258-
if result.is_finite() && (result.fract() != 0.0 || result.log10() > 4.0) {
259-
return None;
260-
}
261-
result
262-
}
263-
_ => unreachable!(),
264-
};
265-
Some(ConstantValue::Number(val))
239+
Some(ConstantValue::Number(lval - rval))
240+
}
241+
BinaryOperator::Division => {
242+
let lval = left.evaluate_value_to_number(ctx)?;
243+
let rval = right.evaluate_value_to_number(ctx)?;
244+
Some(ConstantValue::Number(lval / rval))
245+
}
246+
BinaryOperator::Remainder => {
247+
let lval = left.evaluate_value_to_number(ctx)?;
248+
let rval = right.evaluate_value_to_number(ctx)?;
249+
Some(ConstantValue::Number(if rval.is_zero() { f64::NAN } else { lval % rval }))
250+
}
251+
BinaryOperator::Multiplication => {
252+
let lval = left.evaluate_value_to_number(ctx)?;
253+
let rval = right.evaluate_value_to_number(ctx)?;
254+
Some(ConstantValue::Number(lval * rval))
255+
}
256+
BinaryOperator::Exponential => {
257+
let lval = left.evaluate_value_to_number(ctx)?;
258+
let rval = right.evaluate_value_to_number(ctx)?;
259+
let result = lval.powf(rval);
260+
// For now, ignore the result if it large or has a decimal part
261+
// so that the output does not become bigger than the input.
262+
if result.is_finite() && (result.fract() != 0.0 || result.log10() > 4.0) {
263+
return None;
264+
}
265+
Some(ConstantValue::Number(result))
266266
}
267267
#[expect(clippy::cast_sign_loss)]
268-
BinaryOperator::ShiftLeft
269-
| BinaryOperator::ShiftRight
270-
| BinaryOperator::ShiftRightZeroFill => {
268+
BinaryOperator::ShiftLeft => {
271269
let left = left.evaluate_value_to_number(ctx)?;
272270
let right = right.evaluate_value_to_number(ctx)?;
273271
let left = left.to_int_32();
274272
let right = (right.to_int_32() as u32) & 31;
275-
Some(ConstantValue::Number(match operator {
276-
BinaryOperator::ShiftLeft => f64::from(left << right),
277-
BinaryOperator::ShiftRight => f64::from(left >> right),
278-
BinaryOperator::ShiftRightZeroFill => f64::from((left as u32) >> right),
279-
_ => unreachable!(),
280-
}))
273+
Some(ConstantValue::Number(f64::from(left << right)))
274+
}
275+
#[expect(clippy::cast_sign_loss)]
276+
BinaryOperator::ShiftRight => {
277+
let left = left.evaluate_value_to_number(ctx)?;
278+
let right = right.evaluate_value_to_number(ctx)?;
279+
let left = left.to_int_32();
280+
let right = (right.to_int_32() as u32) & 31;
281+
Some(ConstantValue::Number(f64::from(left >> right)))
282+
}
283+
#[expect(clippy::cast_sign_loss)]
284+
BinaryOperator::ShiftRightZeroFill => {
285+
let left = left.evaluate_value_to_number(ctx)?;
286+
let right = right.evaluate_value_to_number(ctx)?;
287+
let left = left.to_int_32();
288+
let right = (right.to_int_32() as u32) & 31;
289+
Some(ConstantValue::Number(f64::from((left as u32) >> right)))
281290
}
282291
BinaryOperator::LessThan => is_less_than(ctx, left, right).map(|value| match value {
283292
ConstantValue::Undefined => ConstantValue::Boolean(false),
@@ -303,33 +312,35 @@ fn binary_operation_evaluate_value_to<'a>(
303312
_ => unreachable!(),
304313
})
305314
}
306-
BinaryOperator::BitwiseAnd | BinaryOperator::BitwiseOR | BinaryOperator::BitwiseXOR => {
315+
BinaryOperator::BitwiseAnd => {
307316
if left.value_type(ctx).is_bigint() && right.value_type(ctx).is_bigint() {
308-
let left_val = left.evaluate_value_to_bigint(ctx)?;
309-
let right_val = right.evaluate_value_to_bigint(ctx)?;
310-
let result_val: BigInt = match operator {
311-
BinaryOperator::BitwiseAnd => left_val & right_val,
312-
BinaryOperator::BitwiseOR => left_val | right_val,
313-
BinaryOperator::BitwiseXOR => left_val ^ right_val,
314-
_ => unreachable!(),
315-
};
316-
return Some(ConstantValue::BigInt(result_val));
317+
let left_biginit = left.evaluate_value_to_bigint(ctx)?;
318+
let right_bigint = right.evaluate_value_to_bigint(ctx)?;
319+
return Some(ConstantValue::BigInt(left_biginit & right_bigint));
317320
}
318-
let left_num = left.evaluate_value_to_number(ctx);
319-
let right_num = right.evaluate_value_to_number(ctx);
320-
if let (Some(left_val), Some(right_val)) = (left_num, right_num) {
321-
let left_val_int = left_val.to_int_32();
322-
let right_val_int = right_val.to_int_32();
323-
324-
let result_val: f64 = match operator {
325-
BinaryOperator::BitwiseAnd => f64::from(left_val_int & right_val_int),
326-
BinaryOperator::BitwiseOR => f64::from(left_val_int | right_val_int),
327-
BinaryOperator::BitwiseXOR => f64::from(left_val_int ^ right_val_int),
328-
_ => unreachable!(),
329-
};
330-
return Some(ConstantValue::Number(result_val));
321+
let left_int = left.evaluate_value_to_number(ctx)?.to_int_32();
322+
let right_int = right.evaluate_value_to_number(ctx)?.to_int_32();
323+
Some(ConstantValue::Number(f64::from(left_int & right_int)))
324+
}
325+
BinaryOperator::BitwiseOR => {
326+
if left.value_type(ctx).is_bigint() && right.value_type(ctx).is_bigint() {
327+
let left_biginit = left.evaluate_value_to_bigint(ctx)?;
328+
let right_bigint = right.evaluate_value_to_bigint(ctx)?;
329+
return Some(ConstantValue::BigInt(left_biginit | right_bigint));
331330
}
332-
None
331+
let left_int = left.evaluate_value_to_number(ctx)?.to_int_32();
332+
let right_int = right.evaluate_value_to_number(ctx)?.to_int_32();
333+
Some(ConstantValue::Number(f64::from(left_int | right_int)))
334+
}
335+
BinaryOperator::BitwiseXOR => {
336+
if left.value_type(ctx).is_bigint() && right.value_type(ctx).is_bigint() {
337+
let left_biginit = left.evaluate_value_to_bigint(ctx)?;
338+
let right_bigint = right.evaluate_value_to_bigint(ctx)?;
339+
return Some(ConstantValue::BigInt(left_biginit ^ right_bigint));
340+
}
341+
let left_int = left.evaluate_value_to_number(ctx)?.to_int_32();
342+
let right_int = right.evaluate_value_to_number(ctx)?.to_int_32();
343+
Some(ConstantValue::Number(f64::from(left_int ^ right_int)))
333344
}
334345
BinaryOperator::Instanceof => {
335346
if let Expression::Identifier(right_ident) = right {
@@ -348,24 +359,21 @@ fn binary_operation_evaluate_value_to<'a>(
348359
}
349360
None
350361
}
351-
BinaryOperator::StrictEquality
352-
| BinaryOperator::StrictInequality
353-
| BinaryOperator::Equality
354-
| BinaryOperator::Inequality => {
355-
let value = match operator {
356-
BinaryOperator::StrictEquality | BinaryOperator::StrictInequality => {
357-
strict_equality_comparison(ctx, left, right)?
358-
}
359-
BinaryOperator::Equality | BinaryOperator::Inequality => {
360-
abstract_equality_comparison(ctx, left, right)?
361-
}
362-
_ => unreachable!(),
363-
};
364-
Some(ConstantValue::Boolean(match operator {
365-
BinaryOperator::StrictEquality | BinaryOperator::Equality => value,
366-
BinaryOperator::StrictInequality | BinaryOperator::Inequality => !value,
367-
_ => unreachable!(),
368-
}))
362+
BinaryOperator::StrictEquality => {
363+
let value = strict_equality_comparison(ctx, left, right)?;
364+
Some(ConstantValue::Boolean(value))
365+
}
366+
BinaryOperator::StrictInequality => {
367+
let value = strict_equality_comparison(ctx, left, right)?;
368+
Some(ConstantValue::Boolean(!value))
369+
}
370+
BinaryOperator::Equality => {
371+
let value = abstract_equality_comparison(ctx, left, right)?;
372+
Some(ConstantValue::Boolean(value))
373+
}
374+
BinaryOperator::Inequality => {
375+
let value = abstract_equality_comparison(ctx, left, right)?;
376+
Some(ConstantValue::Boolean(!value))
369377
}
370378
BinaryOperator::In => None,
371379
}

0 commit comments

Comments
 (0)