mirror of
https://github.com/fergalmoran/ladybird.git
synced 2025-12-27 03:37:53 +00:00
LibJS/Bytecode: Round constant operands of bitwise binary expressions
This helps some of the Cloudflare Turnstile stuff run faster, since they are deliberately screwing with JS engines by asking us to do a bunch of bitwise operations on e.g 65535.56 By rounding such values in bytecode generation, the interpreter can stay on the happy path while executing, and finish quite a bit faster.
This commit is contained in:
committed by
Alexander Kalenik
parent
ca8dc8f61f
commit
448f837d38
@@ -90,9 +90,59 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> BinaryExpression::gener
|
||||
return dst;
|
||||
}
|
||||
|
||||
auto lhs = TRY(m_lhs->generate_bytecode(generator)).value();
|
||||
auto rhs = TRY(m_rhs->generate_bytecode(generator)).value();
|
||||
// OPTIMIZATION: If LHS and/or RHS are numeric literals, we make sure they are converted to i32/u32
|
||||
// as appropriate, to avoid having to perform these conversions at runtime.
|
||||
|
||||
auto get_left_side = [&](Expression const& side) -> CodeGenerationErrorOr<Optional<ScopedOperand>> {
|
||||
switch (m_op) {
|
||||
case BinaryOp::BitwiseAnd:
|
||||
case BinaryOp::BitwiseOr:
|
||||
case BinaryOp::BitwiseXor:
|
||||
case BinaryOp::LeftShift:
|
||||
case BinaryOp::RightShift:
|
||||
case BinaryOp::UnsignedRightShift:
|
||||
// LHS will always be converted to i32 for these ops.
|
||||
if (side.is_numeric_literal()) {
|
||||
auto value = MUST(static_cast<NumericLiteral const&>(side).value().to_i32(generator.vm()));
|
||||
return generator.add_constant(Value(value));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return side.generate_bytecode(generator);
|
||||
};
|
||||
|
||||
auto get_right_side = [&](Expression const& side) -> CodeGenerationErrorOr<Optional<ScopedOperand>> {
|
||||
switch (m_op) {
|
||||
case BinaryOp::BitwiseAnd:
|
||||
case BinaryOp::BitwiseOr:
|
||||
case BinaryOp::BitwiseXor:
|
||||
// RHS will always be converted to i32 for these ops.
|
||||
if (side.is_numeric_literal()) {
|
||||
auto value = MUST(static_cast<NumericLiteral const&>(side).value().to_i32(generator.vm()));
|
||||
return generator.add_constant(Value(value));
|
||||
}
|
||||
break;
|
||||
case BinaryOp::LeftShift:
|
||||
case BinaryOp::RightShift:
|
||||
case BinaryOp::UnsignedRightShift:
|
||||
// RHS will always be converted to u32 for these ops.
|
||||
if (side.is_numeric_literal()) {
|
||||
auto value = MUST(static_cast<NumericLiteral const&>(side).value().to_u32(generator.vm()));
|
||||
return generator.add_constant(Value(value));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return side.generate_bytecode(generator);
|
||||
};
|
||||
|
||||
auto lhs = TRY(get_left_side(*m_lhs)).value();
|
||||
auto rhs = TRY(get_right_side(*m_rhs)).value();
|
||||
auto dst = choose_dst(generator, preferred_dst);
|
||||
switch (m_op) {
|
||||
case BinaryOp::Addition:
|
||||
|
||||
Reference in New Issue
Block a user