From 900f209b34c6bc5d85ba16870f3f90786aa50eae Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 27 Mar 2025 15:11:15 +0000 Subject: [PATCH] LibJS: Make Optional use less space Shrink these down from 12 bytes to 8 bytes, which helps make many bytecode instructions smaller. --- Libraries/LibJS/Bytecode/Operand.h | 100 +++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/Libraries/LibJS/Bytecode/Operand.h b/Libraries/LibJS/Bytecode/Operand.h index 8a2a1b4fedf..e4f619969b6 100644 --- a/Libraries/LibJS/Bytecode/Operand.h +++ b/Libraries/LibJS/Bytecode/Operand.h @@ -14,6 +14,7 @@ namespace JS::Bytecode { class Operand { public: enum class Type { + Invalid, Register, Local, Constant, @@ -46,3 +47,102 @@ private: }; } + +namespace AK { +template<> +class Optional : public OptionalBase { + template + friend class Optional; + +public: + using ValueType = JS::Bytecode::Operand; + + Optional() = default; + + template V> + Optional(V) { } + + Optional(Optional const& other) + { + if (other.has_value()) + m_value = other.m_value; + } + + Optional(Optional&& other) + : m_value(other.m_value) + { + } + + template + requires(!IsSame>) + explicit(!IsConvertible) Optional(U&& value) + requires(!IsSame, Optional> && IsConstructible) + : m_value(forward(value)) + { + } + + template V> + Optional& operator=(V) + { + clear(); + return *this; + } + + Optional& operator=(Optional const& other) + { + if (this != &other) { + clear(); + m_value = other.m_value; + } + return *this; + } + + Optional& operator=(Optional&& other) + { + if (this != &other) { + clear(); + m_value = other.m_value; + } + return *this; + } + + void clear() + { + m_value = JS::Bytecode::Operand { JS::Bytecode::Operand::Type::Invalid, 0 }; + } + + [[nodiscard]] bool has_value() const + { + return m_value.type() != JS::Bytecode::Operand::Type::Invalid; + } + + [[nodiscard]] JS::Bytecode::Operand& value() & + { + VERIFY(has_value()); + return m_value; + } + + [[nodiscard]] JS::Bytecode::Operand const& value() const& + { + VERIFY(has_value()); + return m_value; + } + + [[nodiscard]] JS::Bytecode::Operand value() && + { + return release_value(); + } + + [[nodiscard]] JS::Bytecode::Operand release_value() + { + VERIFY(has_value()); + JS::Bytecode::Operand released_value = m_value; + clear(); + return released_value; + } + +private: + JS::Bytecode::Operand m_value { JS::Bytecode::Operand::Type::Invalid, 0 }; +}; + +}