Files
ladybird/Userland/Libraries/LibJS/Bytecode/Register.h
Idan Horowitz 58e2fe895c LibJS: Stash thrown exception in a register before executing finalizer
This kills 2 birds with one stone:
1. It makes sure generated check_exception() calls in the finalizer
   don't mis-read the pending exception as caused by their matching
   operation.
2. It implicitly ensures that terminated finally blocks (by a return
   statement) overwrite any pending exceptions, since they will never
   execute the ContinuePendingUnwind operation that restores the
   stashed exception.
This additional logic is required in the JIT (as opposed to the
interpreter), since the JIT uses the exception register to store and
check the possibly-exceptional results from each individual operation,
while the interpreter only modifies it when an operation has thrown an
exception.
2023-11-03 20:27:45 +01:00

80 lines
1.8 KiB
C++

/*
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Format.h>
namespace JS::Bytecode {
class Register {
public:
constexpr static u32 accumulator_index = 0;
static constexpr Register accumulator()
{
return Register(accumulator_index);
}
constexpr static u32 saved_return_value_index = 1;
static constexpr Register saved_return_value()
{
return Register(saved_return_value_index);
}
static constexpr u32 exception_index = 2;
static constexpr Register exception()
{
return Register(exception_index);
}
static constexpr Register this_value()
{
constexpr u32 this_value_index = 3;
return Register(this_value_index);
}
static constexpr Register return_value()
{
constexpr u32 return_value_index = 4;
return Register(return_value_index);
}
static constexpr Register saved_exception()
{
constexpr u32 saved_exception_index = 5;
return Register(saved_exception_index);
}
static constexpr u32 reserved_register_count = 6;
constexpr explicit Register(u32 index)
: m_index(index)
{
}
constexpr bool operator==(Register reg) const { return m_index == reg.index(); }
constexpr u32 index() const { return m_index; }
private:
u32 m_index;
};
}
template<>
struct AK::Formatter<JS::Bytecode::Register> : AK::Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, JS::Bytecode::Register const& value)
{
if (value.index() == JS::Bytecode::Register::accumulator_index)
return builder.put_string("acc"sv);
return AK::Formatter<FormatString>::format(builder, "${}"sv, value.index());
}
};