mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
LibJS/Bytecode: Dedicated instructions for postfix increment/decrement
Instead of splitting the postfix variants into ToNumeric + Inc/Dec, we now have dedicated PostfixIncrement and PostfixDecrement instructions that handle both outputs in one go.
This commit is contained in:
parent
c4f49e343a
commit
9d9b737a58
Notes:
sideshowbarker
2024-07-17 03:00:02 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/9d9b737a58 Pull-request: https://github.com/SerenityOS/serenity/pull/23269
4 changed files with 96 additions and 27 deletions
|
@ -2373,15 +2373,22 @@ Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> UpdateExpression::g
|
|||
auto reference = TRY(generator.emit_load_from_reference(*m_argument));
|
||||
|
||||
Optional<Bytecode::Operand> previous_value_for_postfix;
|
||||
if (!m_prefixed) {
|
||||
previous_value_for_postfix = Bytecode::Operand(generator.allocate_register());
|
||||
generator.emit<Bytecode::Op::ToNumeric>(*previous_value_for_postfix, *reference.loaded_value);
|
||||
}
|
||||
|
||||
if (m_op == UpdateOp::Increment)
|
||||
generator.emit<Bytecode::Op::Increment>(*reference.loaded_value);
|
||||
else
|
||||
generator.emit<Bytecode::Op::Decrement>(*reference.loaded_value);
|
||||
if (m_op == UpdateOp::Increment) {
|
||||
if (m_prefixed) {
|
||||
generator.emit<Bytecode::Op::Increment>(*reference.loaded_value);
|
||||
} else {
|
||||
previous_value_for_postfix = Bytecode::Operand(generator.allocate_register());
|
||||
generator.emit<Bytecode::Op::PostfixIncrement>(*previous_value_for_postfix, *reference.loaded_value);
|
||||
}
|
||||
} else {
|
||||
if (m_prefixed) {
|
||||
generator.emit<Bytecode::Op::Decrement>(*reference.loaded_value);
|
||||
} else {
|
||||
previous_value_for_postfix = Bytecode::Operand(generator.allocate_register());
|
||||
generator.emit<Bytecode::Op::PostfixDecrement>(*previous_value_for_postfix, *reference.loaded_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (is<Identifier>(*m_argument))
|
||||
(void)TRY(generator.emit_store_to_reference(static_cast<Identifier const&>(*m_argument), *reference.loaded_value));
|
||||
|
|
|
@ -91,6 +91,8 @@
|
|||
O(NewString) \
|
||||
O(NewTypeError) \
|
||||
O(Not) \
|
||||
O(PostfixDecrement) \
|
||||
O(PostfixIncrement) \
|
||||
O(PutById) \
|
||||
O(PutByIdWithThis) \
|
||||
O(PutByValue) \
|
||||
|
@ -111,7 +113,6 @@
|
|||
O(ThrowIfNotObject) \
|
||||
O(ThrowIfNullish) \
|
||||
O(ThrowIfTDZ) \
|
||||
O(ToNumeric) \
|
||||
O(Typeof) \
|
||||
O(TypeofVariable) \
|
||||
O(UnaryMinus) \
|
||||
|
|
|
@ -1113,6 +1113,31 @@ ThrowCompletionOr<void> Increment::execute_impl(Bytecode::Interpreter& interpret
|
|||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> PostfixIncrement::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& vm = interpreter.vm();
|
||||
auto old_value = interpreter.get(m_src);
|
||||
|
||||
// OPTIMIZATION: Fast path for Int32 values.
|
||||
if (old_value.is_int32()) {
|
||||
auto integer_value = old_value.as_i32();
|
||||
if (integer_value != NumericLimits<i32>::max()) [[likely]] {
|
||||
interpreter.set(m_dst, old_value);
|
||||
interpreter.set(m_src, Value { integer_value + 1 });
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
old_value = TRY(old_value.to_numeric(vm));
|
||||
interpreter.set(m_dst, old_value);
|
||||
|
||||
if (old_value.is_number())
|
||||
interpreter.set(m_src, Value(old_value.as_double() + 1));
|
||||
else
|
||||
interpreter.set(m_src, BigInt::create(vm, old_value.as_bigint().big_integer().plus(Crypto::SignedBigInteger { 1 })));
|
||||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> Decrement::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& vm = interpreter.vm();
|
||||
|
@ -1127,6 +1152,21 @@ ThrowCompletionOr<void> Decrement::execute_impl(Bytecode::Interpreter& interpret
|
|||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> PostfixDecrement::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& vm = interpreter.vm();
|
||||
auto old_value = interpreter.get(m_src);
|
||||
|
||||
old_value = TRY(old_value.to_numeric(vm));
|
||||
interpreter.set(m_dst, old_value);
|
||||
|
||||
if (old_value.is_number())
|
||||
interpreter.set(m_src, Value(old_value.as_double() - 1));
|
||||
else
|
||||
interpreter.set(m_src, BigInt::create(vm, old_value.as_bigint().big_integer().minus(Crypto::SignedBigInteger { 1 })));
|
||||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> Throw::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
return throw_completion(interpreter.get(src()));
|
||||
|
@ -1356,12 +1396,6 @@ ThrowCompletionOr<void> TypeofVariable::execute_impl(Bytecode::Interpreter& inte
|
|||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> ToNumeric::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
interpreter.set(dst(), TRY(interpreter.get(src()).to_numeric(interpreter.vm())));
|
||||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> BlockDeclarationInstantiation::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& vm = interpreter.vm();
|
||||
|
@ -1763,9 +1797,23 @@ ByteString Increment::to_byte_string_impl(Bytecode::Executable const& executable
|
|||
return ByteString::formatted("Increment {}", format_operand("dst"sv, m_dst, executable));
|
||||
}
|
||||
|
||||
ByteString Decrement::to_byte_string_impl(Bytecode::Executable const&) const
|
||||
ByteString PostfixIncrement::to_byte_string_impl(Bytecode::Executable const& executable) const
|
||||
{
|
||||
return "Decrement";
|
||||
return ByteString::formatted("PostfixIncrement {}, {}",
|
||||
format_operand("dst"sv, m_dst, executable),
|
||||
format_operand("src"sv, m_dst, executable));
|
||||
}
|
||||
|
||||
ByteString Decrement::to_byte_string_impl(Bytecode::Executable const& executable) const
|
||||
{
|
||||
return ByteString::formatted("Decrement {}", format_operand("dst"sv, m_dst, executable));
|
||||
}
|
||||
|
||||
ByteString PostfixDecrement::to_byte_string_impl(Bytecode::Executable const& executable) const
|
||||
{
|
||||
return ByteString::formatted("PostfixDecrement {}, {}",
|
||||
format_operand("dst"sv, m_dst, executable),
|
||||
format_operand("src"sv, m_dst, executable));
|
||||
}
|
||||
|
||||
ByteString Throw::to_byte_string_impl(Bytecode::Executable const& executable) const
|
||||
|
@ -1974,13 +2022,6 @@ ByteString TypeofVariable::to_byte_string_impl(Bytecode::Executable const& execu
|
|||
executable.identifier_table->get(m_identifier));
|
||||
}
|
||||
|
||||
ByteString ToNumeric::to_byte_string_impl(Bytecode::Executable const& executable) const
|
||||
{
|
||||
return ByteString::formatted("ToNumeric {}, {}",
|
||||
format_operand("dst"sv, m_dst, executable),
|
||||
format_operand("src"sv, m_src, executable));
|
||||
}
|
||||
|
||||
ByteString BlockDeclarationInstantiation::to_byte_string_impl(Bytecode::Executable const&) const
|
||||
{
|
||||
return "BlockDeclarationInstantiation"sv;
|
||||
|
|
|
@ -1347,6 +1347,26 @@ private:
|
|||
Operand m_dst;
|
||||
};
|
||||
|
||||
class PostfixIncrement final : public Instruction {
|
||||
public:
|
||||
explicit PostfixIncrement(Operand dst, Operand src)
|
||||
: Instruction(Type::PostfixIncrement, sizeof(*this))
|
||||
, m_dst(dst)
|
||||
, m_src(src)
|
||||
{
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
|
||||
ByteString to_byte_string_impl(Bytecode::Executable const&) const;
|
||||
|
||||
Operand dst() const { return m_dst; }
|
||||
Operand src() const { return m_src; }
|
||||
|
||||
private:
|
||||
Operand m_dst;
|
||||
Operand m_src;
|
||||
};
|
||||
|
||||
class Decrement final : public Instruction {
|
||||
public:
|
||||
explicit Decrement(Operand dst)
|
||||
|
@ -1364,10 +1384,10 @@ private:
|
|||
Operand m_dst;
|
||||
};
|
||||
|
||||
class ToNumeric final : public Instruction {
|
||||
class PostfixDecrement final : public Instruction {
|
||||
public:
|
||||
explicit ToNumeric(Operand dst, Operand src)
|
||||
: Instruction(Type::ToNumeric, sizeof(*this))
|
||||
explicit PostfixDecrement(Operand dst, Operand src)
|
||||
: Instruction(Type::PostfixDecrement, sizeof(*this))
|
||||
, m_dst(dst)
|
||||
, m_src(src)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue