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

LibJS: Make Executable ref-counted and let instruction iterator co-own it

This ensures that the instruction stream pointed at by the instruction
iterator remains valid as long as the iterator exists.
This commit is contained in:
Andreas Kling 2023-10-03 08:18:10 +02:00
parent b1ee5c8738
commit c14db6ab12
9 changed files with 61 additions and 26 deletions

View file

@ -5,9 +5,34 @@
*/ */
#include <LibJS/Bytecode/Executable.h> #include <LibJS/Bytecode/Executable.h>
#include <LibJS/SourceCode.h>
namespace JS::Bytecode { namespace JS::Bytecode {
Executable::Executable(
NonnullOwnPtr<IdentifierTable> identifier_table,
NonnullOwnPtr<StringTable> string_table,
NonnullOwnPtr<RegexTable> regex_table,
NonnullRefPtr<SourceCode const> source_code,
size_t number_of_property_lookup_caches,
size_t number_of_global_variable_caches,
size_t number_of_registers,
Vector<NonnullOwnPtr<BasicBlock>> basic_blocks,
bool is_strict_mode)
: basic_blocks(move(basic_blocks))
, string_table(move(string_table))
, identifier_table(move(identifier_table))
, regex_table(move(regex_table))
, source_code(move(source_code))
, number_of_registers(number_of_registers)
, is_strict_mode(is_strict_mode)
{
property_lookup_caches.resize(number_of_property_lookup_caches);
global_variable_caches.resize(number_of_global_variable_caches);
}
Executable::~Executable() = default;
void Executable::dump() const void Executable::dump() const
{ {
dbgln("\033[33;1mJS::Bytecode::Executable\033[0m ({})", name); dbgln("\033[33;1mJS::Bytecode::Executable\033[0m ({})", name);

View file

@ -31,7 +31,21 @@ struct SourceRecord {
u32 source_end_offset {}; u32 source_end_offset {};
}; };
struct Executable { class Executable final : public RefCounted<Executable> {
public:
Executable(
NonnullOwnPtr<IdentifierTable>,
NonnullOwnPtr<StringTable>,
NonnullOwnPtr<RegexTable>,
NonnullRefPtr<SourceCode const>,
size_t number_of_property_lookup_caches,
size_t number_of_global_variable_caches,
size_t number_of_registers,
Vector<NonnullOwnPtr<BasicBlock>>,
bool is_strict_mode);
~Executable();
DeprecatedFlyString name; DeprecatedFlyString name;
Vector<PropertyLookupCache> property_lookup_caches; Vector<PropertyLookupCache> property_lookup_caches;
Vector<GlobalVariableCache> global_variable_caches; Vector<GlobalVariableCache> global_variable_caches;

View file

@ -20,7 +20,7 @@ Generator::Generator()
{ {
} }
CodeGenerationErrorOr<NonnullOwnPtr<Executable>> Generator::generate(ASTNode const& node, FunctionKind enclosing_function_kind) CodeGenerationErrorOr<NonnullRefPtr<Executable>> Generator::generate(ASTNode const& node, FunctionKind enclosing_function_kind)
{ {
Generator generator; Generator generator;
generator.switch_to_basic_block(generator.make_block()); generator.switch_to_basic_block(generator.make_block());
@ -56,24 +56,18 @@ CodeGenerationErrorOr<NonnullOwnPtr<Executable>> Generator::generate(ASTNode con
else if (is<FunctionExpression>(node)) else if (is<FunctionExpression>(node))
is_strict_mode = static_cast<FunctionExpression const&>(node).is_strict_mode(); is_strict_mode = static_cast<FunctionExpression const&>(node).is_strict_mode();
Vector<PropertyLookupCache> property_lookup_caches; auto executable = adopt_ref(*new Executable(
property_lookup_caches.resize(generator.m_next_property_lookup_cache); move(generator.m_identifier_table),
move(generator.m_string_table),
move(generator.m_regex_table),
node.source_code(),
generator.m_next_property_lookup_cache,
generator.m_next_global_variable_cache,
generator.m_next_register,
move(generator.m_root_basic_blocks),
is_strict_mode));
Vector<GlobalVariableCache> global_variable_caches; return executable;
global_variable_caches.resize(generator.m_next_global_variable_cache);
return adopt_own(*new Executable {
.name = {},
.property_lookup_caches = move(property_lookup_caches),
.global_variable_caches = move(global_variable_caches),
.basic_blocks = move(generator.m_root_basic_blocks),
.string_table = move(generator.m_string_table),
.identifier_table = move(generator.m_identifier_table),
.regex_table = move(generator.m_regex_table),
.source_code = node.source_code(),
.number_of_registers = generator.m_next_register,
.is_strict_mode = is_strict_mode,
});
} }
void Generator::grow(size_t additional_size) void Generator::grow(size_t additional_size)

View file

@ -30,7 +30,7 @@ public:
Function, Function,
Block, Block,
}; };
static CodeGenerationErrorOr<NonnullOwnPtr<Executable>> generate(ASTNode const&, FunctionKind = FunctionKind::Normal); static CodeGenerationErrorOr<NonnullRefPtr<Executable>> generate(ASTNode const&, FunctionKind = FunctionKind::Normal);
Register allocate_register(); Register allocate_register();

View file

@ -178,13 +178,15 @@ public:
UnrealizedSourceRange source_range() const; UnrealizedSourceRange source_range() const;
RefPtr<SourceCode> source_code() const; RefPtr<SourceCode> source_code() const;
Executable const* executable() const { return m_executable; }
private: private:
Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_ptr); } Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_ptr); }
u8 const* m_begin { nullptr }; u8 const* m_begin { nullptr };
u8 const* m_end { nullptr }; u8 const* m_end { nullptr };
u8 const* m_ptr { nullptr }; u8 const* m_ptr { nullptr };
Executable const* m_executable { nullptr }; RefPtr<Executable const> m_executable;
}; };
} }

View file

@ -407,7 +407,7 @@ void Interpreter::leave_unwind_context()
unwind_contexts().take_last(); unwind_contexts().take_last();
} }
ThrowCompletionOr<NonnullOwnPtr<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, DeprecatedFlyString const& name) ThrowCompletionOr<NonnullRefPtr<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, DeprecatedFlyString const& name)
{ {
auto executable_result = Bytecode::Generator::generate(node, kind); auto executable_result = Bytecode::Generator::generate(node, kind);
if (executable_result.is_error()) if (executable_result.is_error())

View file

@ -110,6 +110,6 @@ private:
extern bool g_dump_bytecode; extern bool g_dump_bytecode;
ThrowCompletionOr<NonnullOwnPtr<Bytecode::Executable>> compile(VM&, ASTNode const& no, JS::FunctionKind kind, DeprecatedFlyString const& name); ThrowCompletionOr<NonnullRefPtr<Bytecode::Executable>> compile(VM&, ASTNode const& no, JS::FunctionKind kind, DeprecatedFlyString const& name);
} }

View file

@ -302,7 +302,7 @@ class MarkedVector;
namespace Bytecode { namespace Bytecode {
class BasicBlock; class BasicBlock;
struct Executable; class Executable;
class Generator; class Generator;
class Instruction; class Instruction;
class Interpreter; class Interpreter;

View file

@ -111,8 +111,8 @@ private:
ThrowCompletionOr<void> function_declaration_instantiation(); ThrowCompletionOr<void> function_declaration_instantiation();
DeprecatedFlyString m_name; DeprecatedFlyString m_name;
OwnPtr<Bytecode::Executable> m_bytecode_executable; RefPtr<Bytecode::Executable> m_bytecode_executable;
Vector<OwnPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables; Vector<NonnullRefPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables;
i32 m_function_length { 0 }; i32 m_function_length { 0 };
Vector<DeprecatedFlyString> m_local_variables_names; Vector<DeprecatedFlyString> m_local_variables_names;