mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-02 01:08:48 +00:00
Before this change both ExecutionContext and CallFrame were created before executing function/module/script with a couple exceptions: - executable created for default function argument evaluation has to run in function's execution context. - `execute_ast_node()` where executable compiled for ASTNode has to be executed in running execution context. This change moves all members previously owned by CallFrame into ExecutionContext, and makes two exceptions where an executable that does not have a corresponding execution context saves and restores registers before running. Now, all execution state lives in a single entity, which makes it a bit easier to reason about and opens opportunities for optimizations, such as moving registers and local variables into a single array.
99 lines
3.4 KiB
C++
99 lines
3.4 KiB
C++
/*
|
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <LibJS/Bytecode/Executable.h>
|
|
#include <LibJS/Bytecode/Label.h>
|
|
#include <LibJS/Bytecode/Register.h>
|
|
#include <LibJS/Forward.h>
|
|
#include <LibJS/Heap/Cell.h>
|
|
#include <LibJS/Runtime/FunctionKind.h>
|
|
#include <LibJS/Runtime/VM.h>
|
|
#include <LibJS/Runtime/Value.h>
|
|
|
|
namespace JS::Bytecode {
|
|
|
|
class InstructionStreamIterator;
|
|
|
|
class Interpreter {
|
|
public:
|
|
explicit Interpreter(VM&);
|
|
~Interpreter();
|
|
|
|
[[nodiscard]] Realm& realm() { return *m_realm; }
|
|
[[nodiscard]] Object& global_object() { return *m_global_object; }
|
|
[[nodiscard]] DeclarativeEnvironment& global_declarative_environment() { return *m_global_declarative_environment; }
|
|
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&);
|
|
|
|
ThrowCompletionOr<Value> run(Bytecode::Executable& executable, Bytecode::BasicBlock const* entry_point = nullptr)
|
|
{
|
|
auto result_and_return_register = run_executable(executable, entry_point);
|
|
return move(result_and_return_register.value);
|
|
}
|
|
|
|
struct ResultAndReturnRegister {
|
|
ThrowCompletionOr<Value> value;
|
|
Value return_register_value;
|
|
};
|
|
ResultAndReturnRegister run_executable(Bytecode::Executable&, Bytecode::BasicBlock const* entry_point);
|
|
|
|
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 vm().running_execution_context().registers[r.index()];
|
|
}
|
|
Value reg(Register const& r) const
|
|
{
|
|
return vm().running_execution_context().registers[r.index()];
|
|
}
|
|
|
|
[[nodiscard]] Value get(Operand) const;
|
|
void set(Operand, Value);
|
|
|
|
void do_return(Value value)
|
|
{
|
|
reg(Register::return_value()) = value;
|
|
reg(Register::exception()) = {};
|
|
}
|
|
|
|
void enter_unwind_context();
|
|
void leave_unwind_context();
|
|
void catch_exception(Operand dst);
|
|
|
|
void enter_object_environment(Object&);
|
|
|
|
Executable& current_executable() { return *m_current_executable; }
|
|
Executable const& current_executable() const { return *m_current_executable; }
|
|
BasicBlock const& current_block() const { return *m_current_block; }
|
|
Optional<InstructionStreamIterator const&> instruction_stream_iterator() const { return m_pc; }
|
|
|
|
Vector<Value>& registers() { return vm().running_execution_context().registers; }
|
|
Vector<Value> const& registers() const { return vm().running_execution_context().registers; }
|
|
|
|
private:
|
|
void run_bytecode();
|
|
|
|
VM& m_vm;
|
|
BasicBlock const* m_scheduled_jump { nullptr };
|
|
GCPtr<Executable> m_current_executable { nullptr };
|
|
BasicBlock const* m_current_block { nullptr };
|
|
GCPtr<Realm> m_realm { nullptr };
|
|
GCPtr<Object> m_global_object { nullptr };
|
|
GCPtr<DeclarativeEnvironment> m_global_declarative_environment { nullptr };
|
|
Optional<InstructionStreamIterator&> m_pc {};
|
|
};
|
|
|
|
extern bool g_dump_bytecode;
|
|
|
|
ThrowCompletionOr<NonnullGCPtr<Bytecode::Executable>> compile(VM&, ASTNode const&, ReadonlySpan<FunctionParameter>, JS::FunctionKind kind, DeprecatedFlyString const& name);
|
|
|
|
}
|