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:
parent
b1ee5c8738
commit
c14db6ab12
9 changed files with 61 additions and 26 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue