mirror of
https://github.com/SerenityOS/serenity
synced 2024-07-21 18:15:58 +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:
parent
b1ee5c8738
commit
c14db6ab12
|
@ -5,9 +5,34 @@
|
|||
*/
|
||||
|
||||
#include <LibJS/Bytecode/Executable.h>
|
||||
#include <LibJS/SourceCode.h>
|
||||
|
||||
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
|
||||
{
|
||||
dbgln("\033[33;1mJS::Bytecode::Executable\033[0m ({})", name);
|
||||
|
|
|
@ -31,7 +31,21 @@ struct SourceRecord {
|
|||
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;
|
||||
Vector<PropertyLookupCache> property_lookup_caches;
|
||||
Vector<GlobalVariableCache> global_variable_caches;
|
||||
|
|
|
@ -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.switch_to_basic_block(generator.make_block());
|
||||
|
@ -56,24 +56,18 @@ CodeGenerationErrorOr<NonnullOwnPtr<Executable>> Generator::generate(ASTNode con
|
|||
else if (is<FunctionExpression>(node))
|
||||
is_strict_mode = static_cast<FunctionExpression const&>(node).is_strict_mode();
|
||||
|
||||
Vector<PropertyLookupCache> property_lookup_caches;
|
||||
property_lookup_caches.resize(generator.m_next_property_lookup_cache);
|
||||
auto executable = adopt_ref(*new Executable(
|
||||
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;
|
||||
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,
|
||||
});
|
||||
return executable;
|
||||
}
|
||||
|
||||
void Generator::grow(size_t additional_size)
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
Function,
|
||||
Block,
|
||||
};
|
||||
static CodeGenerationErrorOr<NonnullOwnPtr<Executable>> generate(ASTNode const&, FunctionKind = FunctionKind::Normal);
|
||||
static CodeGenerationErrorOr<NonnullRefPtr<Executable>> generate(ASTNode const&, FunctionKind = FunctionKind::Normal);
|
||||
|
||||
Register allocate_register();
|
||||
|
||||
|
|
|
@ -178,13 +178,15 @@ public:
|
|||
UnrealizedSourceRange source_range() const;
|
||||
RefPtr<SourceCode> source_code() const;
|
||||
|
||||
Executable const* executable() const { return m_executable; }
|
||||
|
||||
private:
|
||||
Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_ptr); }
|
||||
|
||||
u8 const* m_begin { nullptr };
|
||||
u8 const* m_end { nullptr };
|
||||
u8 const* m_ptr { nullptr };
|
||||
Executable const* m_executable { nullptr };
|
||||
RefPtr<Executable const> m_executable;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -407,7 +407,7 @@ void Interpreter::leave_unwind_context()
|
|||
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);
|
||||
if (executable_result.is_error())
|
||||
|
|
|
@ -110,6 +110,6 @@ private:
|
|||
|
||||
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);
|
||||
|
||||
}
|
||||
|
|
|
@ -302,7 +302,7 @@ class MarkedVector;
|
|||
|
||||
namespace Bytecode {
|
||||
class BasicBlock;
|
||||
struct Executable;
|
||||
class Executable;
|
||||
class Generator;
|
||||
class Instruction;
|
||||
class Interpreter;
|
||||
|
|
|
@ -111,8 +111,8 @@ private:
|
|||
ThrowCompletionOr<void> function_declaration_instantiation();
|
||||
|
||||
DeprecatedFlyString m_name;
|
||||
OwnPtr<Bytecode::Executable> m_bytecode_executable;
|
||||
Vector<OwnPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables;
|
||||
RefPtr<Bytecode::Executable> m_bytecode_executable;
|
||||
Vector<NonnullRefPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables;
|
||||
i32 m_function_length { 0 };
|
||||
Vector<DeprecatedFlyString> m_local_variables_names;
|
||||
|
||||
|
|
Loading…
Reference in a new issue