Skip to content

Commit 719bb68

Browse files
committed
feat(compiler): Generate single emit opcode for negative numbers.
1 parent b895f74 commit 719bb68

2 files changed

Lines changed: 35 additions & 2 deletions

File tree

  • core
    • ast/src/expression/literal
    • engine/src/bytecompiler/expression

core/ast/src/expression/literal/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,27 @@ pub enum LiteralKind {
250250
Undefined,
251251
}
252252

253+
/// Represents a numeric value.
254+
#[derive(Debug, Clone, Copy)]
255+
pub enum Number {
256+
/// An integer.
257+
Int(i32),
258+
/// A floating point number.
259+
Num(f64),
260+
}
261+
262+
impl LiteralKind {
263+
/// Returns [`Number::Int`] for [`LiteralKind::Int`], [`Number::Num`] for [`LiteralKind::Num`], and [`None`] otherwise.
264+
#[must_use]
265+
pub fn as_number(&self) -> Option<Number> {
266+
Some(match self {
267+
Self::Int(int) => Number::Int(*int),
268+
Self::Num(num) => Number::Num(*num),
269+
_ => return None,
270+
})
271+
}
272+
}
273+
253274
/// Manual implementation, because `Undefined` is never constructed during parsing.
254275
#[cfg(feature = "arbitrary")]
255276
impl<'a> arbitrary::Arbitrary<'a> for LiteralKind {

core/engine/src/bytecompiler/expression/unary.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::bytecompiler::{Access, BindingAccessOpcode, ByteCompiler, Register, ToJsString};
22
use boa_ast::Expression;
3+
use boa_ast::expression::literal::Number;
34
use boa_ast::expression::operator::{Unary, unary::UnaryOp};
45

56
impl ByteCompiler<'_> {
@@ -18,8 +19,19 @@ impl ByteCompiler<'_> {
1819
}
1920
}
2021
UnaryOp::Minus => {
21-
self.compile_expr(unary.target(), dst);
22-
self.bytecode.emit_neg(dst.variable());
22+
if let Expression::Literal(literal) = unary.target().flatten()
23+
&& let Some(number) = literal.kind().as_number()
24+
{
25+
match number {
26+
// Handles special case -0
27+
Number::Int(0) => self.emit_store_rational(-0.0, dst),
28+
Number::Int(value) => self.emit_store_integer(-value, dst),
29+
Number::Num(value) => self.emit_store_rational(-value, dst),
30+
}
31+
} else {
32+
self.compile_expr(unary.target(), dst);
33+
self.bytecode.emit_neg(dst.variable());
34+
}
2335
}
2436
UnaryOp::Plus => {
2537
self.compile_expr(unary.target(), dst);

0 commit comments

Comments
 (0)