mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 10:27:35 +00:00
LibJS: Specialize Optional<Completion>
Since Completion has an enum for state we have plenty of space to add an extra type which indicates on empty completion. Since Optional<Completion> is used in every ThrowCompletionOr<...> this saves quite some stack space as most function in LibJS return types like that. This saves 8 bytes for every Optional<Completion>.
This commit is contained in:
parent
8381e7f1e6
commit
6c504e2bff
1 changed files with 136 additions and 1 deletions
|
@ -19,6 +19,7 @@ namespace JS {
|
|||
class [[nodiscard]] Completion {
|
||||
public:
|
||||
enum class Type {
|
||||
Empty,
|
||||
Normal,
|
||||
Break,
|
||||
Continue,
|
||||
|
@ -31,6 +32,7 @@ public:
|
|||
, m_value(move(value))
|
||||
, m_target(move(target))
|
||||
{
|
||||
VERIFY(type != Type::Empty);
|
||||
if (m_value.has_value())
|
||||
VERIFY(!m_value->is_empty());
|
||||
}
|
||||
|
@ -59,7 +61,11 @@ public:
|
|||
Completion(Completion&&) = default;
|
||||
Completion& operator=(Completion&&) = default;
|
||||
|
||||
[[nodiscard]] Type type() const { return m_type; }
|
||||
[[nodiscard]] Type type() const
|
||||
{
|
||||
VERIFY(m_type != Type::Empty);
|
||||
return m_type;
|
||||
}
|
||||
[[nodiscard]] Optional<Value>& value() { return m_value; }
|
||||
[[nodiscard]] Optional<Value> const& value() const { return m_value; }
|
||||
[[nodiscard]] Optional<FlyString>& target() { return m_target; }
|
||||
|
@ -94,11 +100,140 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
class EmptyTag {
|
||||
};
|
||||
friend AK::Optional<Completion>;
|
||||
|
||||
Completion(EmptyTag)
|
||||
: m_type(Type::Empty)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
return m_type == Type::Empty;
|
||||
}
|
||||
|
||||
Type m_type { Type::Normal }; // [[Type]]
|
||||
Optional<Value> m_value; // [[Value]]
|
||||
Optional<FlyString> m_target; // [[Target]]
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace AK {
|
||||
|
||||
template<>
|
||||
class Optional<JS::Completion> {
|
||||
template<typename U>
|
||||
friend class Optional;
|
||||
|
||||
public:
|
||||
using ValueType = JS::Completion;
|
||||
|
||||
Optional()
|
||||
: m_value(JS::Completion(JS::Completion::EmptyTag {}))
|
||||
{
|
||||
}
|
||||
|
||||
Optional(Optional<JS::Completion> const& other)
|
||||
{
|
||||
if (other.has_value())
|
||||
m_value = other.m_value;
|
||||
}
|
||||
|
||||
Optional(Optional&& other)
|
||||
: m_value(other.m_value)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename U = JS::Completion>
|
||||
explicit(!IsConvertible<U&&, JS::Completion>) Optional(U&& value) requires(!IsSame<RemoveCVReference<U>, Optional<JS::Completion>> && IsConstructible<JS::Completion, U&&>)
|
||||
: m_value(forward<U>(value))
|
||||
{
|
||||
}
|
||||
|
||||
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::Completion(JS::Completion::EmptyTag {});
|
||||
}
|
||||
|
||||
[[nodiscard]] bool has_value() const
|
||||
{
|
||||
return !m_value.is_empty();
|
||||
}
|
||||
|
||||
[[nodiscard]] JS::Completion& value() &
|
||||
{
|
||||
VERIFY(has_value());
|
||||
return m_value;
|
||||
}
|
||||
|
||||
[[nodiscard]] JS::Completion const& value() const&
|
||||
{
|
||||
VERIFY(has_value());
|
||||
return m_value;
|
||||
}
|
||||
|
||||
[[nodiscard]] JS::Completion value() &&
|
||||
{
|
||||
return release_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] JS::Completion release_value()
|
||||
{
|
||||
VERIFY(has_value());
|
||||
JS::Completion released_value = m_value;
|
||||
clear();
|
||||
return released_value;
|
||||
}
|
||||
|
||||
JS::Completion value_or(JS::Completion const& fallback) const&
|
||||
{
|
||||
if (has_value())
|
||||
return value();
|
||||
return fallback;
|
||||
}
|
||||
|
||||
[[nodiscard]] JS::Completion value_or(JS::Completion&& fallback) &&
|
||||
{
|
||||
if (has_value())
|
||||
return value();
|
||||
return fallback;
|
||||
}
|
||||
|
||||
JS::Completion const& operator*() const { return value(); }
|
||||
JS::Completion& operator*() { return value(); }
|
||||
|
||||
JS::Completion const* operator->() const { return &value(); }
|
||||
JS::Completion* operator->() { return &value(); }
|
||||
|
||||
private:
|
||||
JS::Completion m_value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace JS {
|
||||
|
||||
template<typename ValueType>
|
||||
class [[nodiscard]] ThrowCompletionOr {
|
||||
public:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue