mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 21:59:07 +00:00
LibJS: Constant-fold unary expressions
!0 and !1 are very common patterns in minified JavaScript, and we should figure out that they're constants. :^)
This commit is contained in:
parent
de892abdba
commit
202cbe7df6
Notes:
github-actions[bot]
2025-03-25 19:15:10 +00:00
Author: https://github.com/awesomekling
Commit: 202cbe7df6
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4087
Reviewed-by: https://github.com/gmta ✅
1 changed files with 25 additions and 8 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2024, Andreas Kling <andreas@ladybird.org>
|
* Copyright (c) 2021-2025, Andreas Kling <andreas@ladybird.org>
|
||||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||||
* Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
|
* Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
|
||||||
* Copyright (c) 2021, Marcin Gasperowicz <xnooga@gmail.com>
|
* Copyright (c) 2021, Marcin Gasperowicz <xnooga@gmail.com>
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
#include <LibJS/Bytecode/StringTable.h>
|
#include <LibJS/Bytecode/StringTable.h>
|
||||||
#include <LibJS/Runtime/Environment.h>
|
#include <LibJS/Runtime/Environment.h>
|
||||||
#include <LibJS/Runtime/ErrorTypes.h>
|
#include <LibJS/Runtime/ErrorTypes.h>
|
||||||
|
#include <LibJS/Runtime/ValueInlines.h>
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
|
@ -78,6 +79,22 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> ExpressionStatement::ge
|
||||||
return m_expression->generate_bytecode(generator);
|
return m_expression->generate_bytecode(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ThrowCompletionOr<ScopedOperand> constant_fold_unary_expression(Generator& generator, Value value, UnaryOp op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case UnaryOp::Minus:
|
||||||
|
return generator.add_constant(Value(-TRY(value.to_double(generator.vm()))));
|
||||||
|
case UnaryOp::Plus:
|
||||||
|
return generator.add_constant(Value(+TRY(value.to_double(generator.vm()))));
|
||||||
|
case UnaryOp::BitwiseNot:
|
||||||
|
return generator.add_constant(TRY(bitwise_not(generator.vm(), value)));
|
||||||
|
case UnaryOp::Not:
|
||||||
|
return generator.add_constant(Value(!value.to_boolean()));
|
||||||
|
default:
|
||||||
|
return throw_completion(js_null());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ThrowCompletionOr<ScopedOperand> constant_fold_binary_expression(Generator& generator, Value lhs, Value rhs, BinaryOp m_op)
|
static ThrowCompletionOr<ScopedOperand> constant_fold_binary_expression(Generator& generator, Value lhs, Value rhs, BinaryOp m_op)
|
||||||
{
|
{
|
||||||
switch (m_op) {
|
switch (m_op) {
|
||||||
|
@ -328,13 +345,6 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> UnaryExpression::genera
|
||||||
{
|
{
|
||||||
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
||||||
|
|
||||||
// OPTIMIZATION: Turn expressions like `-1` into a constant.
|
|
||||||
if (m_op == UnaryOp::Minus && is<NumericLiteral>(*m_lhs)) {
|
|
||||||
auto& numeric_literal = static_cast<NumericLiteral const&>(*m_lhs);
|
|
||||||
auto value = numeric_literal.value();
|
|
||||||
return generator.add_constant(Value(-value.as_double()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_op == UnaryOp::Delete)
|
if (m_op == UnaryOp::Delete)
|
||||||
return generator.emit_delete_reference(m_lhs);
|
return generator.emit_delete_reference(m_lhs);
|
||||||
|
|
||||||
|
@ -345,6 +355,13 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> UnaryExpression::genera
|
||||||
|
|
||||||
auto dst = choose_dst(generator, preferred_dst);
|
auto dst = choose_dst(generator, preferred_dst);
|
||||||
|
|
||||||
|
if (src.has_value() && src.value().operand().is_constant()) {
|
||||||
|
// OPTIMIZATION: Do some basic constant folding for unary operations on numbers.
|
||||||
|
auto value = generator.get_constant(*src);
|
||||||
|
if (auto result = constant_fold_unary_expression(generator, value, m_op); !result.is_error())
|
||||||
|
return result.release_value();
|
||||||
|
}
|
||||||
|
|
||||||
switch (m_op) {
|
switch (m_op) {
|
||||||
case UnaryOp::BitwiseNot:
|
case UnaryOp::BitwiseNot:
|
||||||
generator.emit<Bytecode::Op::BitwiseNot>(dst, *src);
|
generator.emit<Bytecode::Op::BitwiseNot>(dst, *src);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue