mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:37:34 +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 {
|
class [[nodiscard]] Completion {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
|
Empty,
|
||||||
Normal,
|
Normal,
|
||||||
Break,
|
Break,
|
||||||
Continue,
|
Continue,
|
||||||
|
@ -31,6 +32,7 @@ public:
|
||||||
, m_value(move(value))
|
, m_value(move(value))
|
||||||
, m_target(move(target))
|
, m_target(move(target))
|
||||||
{
|
{
|
||||||
|
VERIFY(type != Type::Empty);
|
||||||
if (m_value.has_value())
|
if (m_value.has_value())
|
||||||
VERIFY(!m_value->is_empty());
|
VERIFY(!m_value->is_empty());
|
||||||
}
|
}
|
||||||
|
@ -59,7 +61,11 @@ public:
|
||||||
Completion(Completion&&) = default;
|
Completion(Completion&&) = default;
|
||||||
Completion& operator=(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>& value() { return m_value; }
|
||||||
[[nodiscard]] Optional<Value> const& value() const { return m_value; }
|
[[nodiscard]] Optional<Value> const& value() const { return m_value; }
|
||||||
[[nodiscard]] Optional<FlyString>& target() { return m_target; }
|
[[nodiscard]] Optional<FlyString>& target() { return m_target; }
|
||||||
|
@ -94,11 +100,140 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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]]
|
Type m_type { Type::Normal }; // [[Type]]
|
||||||
Optional<Value> m_value; // [[Value]]
|
Optional<Value> m_value; // [[Value]]
|
||||||
Optional<FlyString> m_target; // [[Target]]
|
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>
|
template<typename ValueType>
|
||||||
class [[nodiscard]] ThrowCompletionOr {
|
class [[nodiscard]] ThrowCompletionOr {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue