1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:47:45 +00:00

LibJS/Bytecode: Add Bytecode::Operand

An Operand is either a register, a local, or a constant (index into the
executable's constant table)
This commit is contained in:
Andreas Kling 2024-02-02 10:19:17 +01:00
parent c0ec924dc9
commit 3466771492
6 changed files with 85 additions and 1 deletions

View file

@ -42,4 +42,10 @@ RefPtr<SourceCode> InstructionStreamIterator::source_code() const
return m_executable ? m_executable->source_code.ptr() : nullptr;
}
Operand::Operand(Register reg)
: m_type(Type::Register)
, m_index(reg.index())
{
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2024, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

View file

@ -67,6 +67,34 @@ void Interpreter::visit_edges(Cell::Visitor& visitor)
}
}
Value Interpreter::get(Operand op) const
{
switch (op.type()) {
case Operand::Type::Register:
return reg(Register { op.index() });
case Operand::Type::Local:
return vm().running_execution_context().locals[op.index()];
case Operand::Type::Constant:
return current_executable().constants[op.index()];
}
VERIFY_NOT_REACHED();
}
void Interpreter::set(Operand op, Value value)
{
switch (op.type()) {
case Operand::Type::Register:
reg(Register { op.index() }) = value;
return;
case Operand::Type::Local:
vm().running_execution_context().locals[op.index()] = value;
return;
case Operand::Type::Constant:
VERIFY_NOT_REACHED();
}
VERIFY_NOT_REACHED();
}
// 16.1.6 ScriptEvaluation ( scriptRecord ), https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation
ThrowCompletionOr<Value> Interpreter::run(Script& script_record, JS::GCPtr<Environment> lexical_environment_override)
{

View file

@ -53,6 +53,7 @@ public:
Realm& realm();
VM& vm() { return m_vm; }
VM const& vm() const { return m_vm; }
ThrowCompletionOr<Value> run(Script&, JS::GCPtr<Environment> lexical_environment_override = nullptr);
ThrowCompletionOr<Value> run(SourceTextModule&);
@ -72,6 +73,10 @@ public:
ALWAYS_INLINE Value& accumulator() { return reg(Register::accumulator()); }
ALWAYS_INLINE Value& saved_return_value() { return reg(Register::saved_return_value()); }
Value& reg(Register const& r) { return registers()[r.index()]; }
Value reg(Register const& r) const { return registers()[r.index()]; }
[[nodiscard]] Value get(Operand) const;
void set(Operand, Value);
auto& saved_lexical_environment_stack() { return call_frame().saved_lexical_environments; }
auto& unwind_contexts() { return call_frame().unwind_contexts; }

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2024, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
#include <LibJS/Forward.h>
namespace JS::Bytecode {
class Operand {
public:
enum class Type {
Register,
Local,
Constant,
};
[[nodiscard]] bool operator==(Operand const&) const = default;
explicit Operand(Type type, u32 index)
: m_type(type)
, m_index(index)
{
}
explicit Operand(Register);
[[nodiscard]] bool is_register() const { return m_type == Type::Register; }
[[nodiscard]] bool is_local() const { return m_type == Type::Local; }
[[nodiscard]] bool is_constant() const { return m_type == Type::Constant; }
[[nodiscard]] Type type() const { return m_type; }
[[nodiscard]] u32 index() const { return m_index; }
private:
Type m_type {};
u32 m_index { 0 };
};
}