LibJS: Shrink ThrowCompletionOr<void>
Some checks failed
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Build Dev Container Image / build (push) Has been cancelled

By specializing this template and using the special empty JS::Value as a
marker for the `void` state, we shrink this very common class from 16
bytes to 8 bytes.

This allows bytecode instruction handlers to return their result in a
single 64-bit register, allowing tighter code generation.
This commit is contained in:
Andreas Kling 2025-04-05 16:05:52 +02:00 committed by Andreas Kling
parent c5a239b8c4
commit 15e2c78e9a
Notes: github-actions[bot] 2025-04-05 19:35:06 +00:00

View file

@ -298,9 +298,41 @@ private:
};
template<>
class [[nodiscard]] ThrowCompletionOr<void> : public ThrowCompletionOr<Empty> {
class [[nodiscard]] ThrowCompletionOr<void> {
public:
using ThrowCompletionOr<Empty>::ThrowCompletionOr;
ALWAYS_INLINE ThrowCompletionOr()
: m_value(js_special_empty_value())
{
}
ALWAYS_INLINE ThrowCompletionOr(Empty)
: m_value(js_special_empty_value())
{
}
// Not `explicit` on purpose so that `return vm.throw_completion<Error>(...);` is possible.
ALWAYS_INLINE ThrowCompletionOr(Completion throw_completion)
: m_value(throw_completion.release_error().value())
{
}
ALWAYS_INLINE ThrowCompletionOr(ThrowCompletionOr const&) = default;
ALWAYS_INLINE ThrowCompletionOr& operator=(ThrowCompletionOr const&) = default;
ALWAYS_INLINE ThrowCompletionOr(ThrowCompletionOr&&) = default;
ALWAYS_INLINE ThrowCompletionOr& operator=(ThrowCompletionOr&&) = default;
[[nodiscard]] bool is_throw_completion() const { return !m_value.is_special_empty_value(); }
[[nodiscard]] Completion throw_completion() const { return error(); }
[[nodiscard]] Value error_value() const { return m_value; }
// These are for compatibility with the TRY() macro in AK.
[[nodiscard]] bool is_error() const { return !m_value.is_special_empty_value(); }
Empty release_value() { return {}; }
Completion error() const { return Completion { Completion::Type::Throw, m_value }; }
Completion release_error() { return error(); }
private:
Value m_value;
};
ThrowCompletionOr<Value> await(VM&, Value);