Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LibJS: Emit bytecode for function declaration instantiation #24272

Merged
merged 5 commits into from
May 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions Userland/Libraries/LibJS/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <LibJS/Bytecode/CodeGenerationError.h>
#include <LibJS/Bytecode/Executable.h>
#include <LibJS/Bytecode/IdentifierTable.h>
#include <LibJS/Bytecode/Op.h>
#include <LibJS/Bytecode/Operand.h>
#include <LibJS/Bytecode/ScopedOperand.h>
#include <LibJS/Forward.h>
Expand Down Expand Up @@ -646,6 +647,8 @@ struct BindingPattern : RefCounted<BindingPattern> {

bool contains_expression() const;

Bytecode::CodeGenerationErrorOr<void> generate_bytecode(Bytecode::Generator&, Bytecode::Op::SetVariable::InitializationMode initialization_mode, Bytecode::ScopedOperand const& object, bool create_variables) const;

Vector<BindingEntry> entries;
Kind kind { Kind::Object };
};
Expand Down Expand Up @@ -711,6 +714,11 @@ class FunctionNode {
FunctionKind kind() const { return m_kind; }
UsesThis uses_this() const { return m_uses_this; }

virtual bool has_name() const = 0;
virtual Value instantiate_ordinary_function_expression(VM&, DeprecatedFlyString given_name) const = 0;

virtual ~FunctionNode() {};

protected:
FunctionNode(RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, Vector<FunctionParameter> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Vector<DeprecatedFlyString> local_variables_names, UsesThis uses_this)
: m_name(move(name))
Expand Down Expand Up @@ -770,6 +778,11 @@ class FunctionDeclaration final

void set_should_do_additional_annexB_steps() { m_is_hoisted = true; }

bool has_name() const override { return true; }
Value instantiate_ordinary_function_expression(VM&, DeprecatedFlyString) const override { VERIFY_NOT_REACHED(); }

virtual ~FunctionDeclaration() {};

private:
bool m_is_hoisted { false };
};
Expand All @@ -791,9 +804,11 @@ class FunctionExpression final
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;

bool has_name() const { return !name().is_empty(); }
bool has_name() const override { return !name().is_empty(); }

Value instantiate_ordinary_function_expression(VM&, DeprecatedFlyString given_name) const override;

Value instantiate_ordinary_function_expression(VM&, DeprecatedFlyString given_name) const;
virtual ~FunctionExpression() {};

private:
virtual bool is_function_expression() const override { return true; }
Expand Down
25 changes: 11 additions & 14 deletions Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,6 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> SuperCall::generate_byt
return dst;
}

static Bytecode::CodeGenerationErrorOr<void> generate_binding_pattern_bytecode(Bytecode::Generator& generator, BindingPattern const& pattern, Bytecode::Op::SetVariable::InitializationMode, ScopedOperand const& input_value, bool create_variables);

Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> AssignmentExpression::generate_bytecode(Bytecode::Generator& generator, Optional<ScopedOperand> preferred_dst) const
{
Bytecode::Generator::SourceLocationScope scope(generator, *this);
Expand Down Expand Up @@ -588,7 +586,7 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> AssignmentExpression::g
auto rval = TRY(m_rhs->generate_bytecode(generator)).value();

// 5. Perform ? DestructuringAssignmentEvaluation of assignmentPattern with argument rval.
TRY(generate_binding_pattern_bytecode(generator, pattern, Bytecode::Op::SetVariable::InitializationMode::Set, rval, false));
TRY(pattern->generate_bytecode(generator, Bytecode::Op::SetVariable::InitializationMode::Set, rval, false));

// 6. Return rval.
return rval;
Expand Down Expand Up @@ -1265,7 +1263,7 @@ static Bytecode::CodeGenerationErrorOr<void> generate_object_binding_pattern_byt
auto& binding_pattern = *alias.get<NonnullRefPtr<BindingPattern const>>();
auto nested_value = generator.allocate_register();
generator.emit<Bytecode::Op::Mov>(nested_value, value);
TRY(generate_binding_pattern_bytecode(generator, binding_pattern, initialization_mode, nested_value, create_variables));
TRY(binding_pattern.generate_bytecode(generator, initialization_mode, nested_value, create_variables));
} else if (alias.has<Empty>()) {
if (name.has<NonnullRefPtr<Expression const>>()) {
// This needs some sort of SetVariableByValue opcode, as it's a runtime binding
Expand Down Expand Up @@ -1336,7 +1334,7 @@ static Bytecode::CodeGenerationErrorOr<void> generate_array_binding_pattern_byte
return {};
},
[&](NonnullRefPtr<BindingPattern const> const& pattern) -> Bytecode::CodeGenerationErrorOr<void> {
return generate_binding_pattern_bytecode(generator, pattern, initialization_mode, value, create_variables);
return pattern->generate_bytecode(generator, initialization_mode, value, create_variables);
},
[&](NonnullRefPtr<MemberExpression const> const& expr) -> Bytecode::CodeGenerationErrorOr<void> {
(void)generator.emit_store_to_reference(*expr, value);
Expand Down Expand Up @@ -1469,12 +1467,12 @@ static Bytecode::CodeGenerationErrorOr<void> generate_array_binding_pattern_byte
return {};
}

static Bytecode::CodeGenerationErrorOr<void> generate_binding_pattern_bytecode(Bytecode::Generator& generator, BindingPattern const& pattern, Bytecode::Op::SetVariable::InitializationMode initialization_mode, ScopedOperand const& input_value, bool create_variables)
Bytecode::CodeGenerationErrorOr<void> BindingPattern::generate_bytecode(Bytecode::Generator& generator, Bytecode::Op::SetVariable::InitializationMode initialization_mode, ScopedOperand const& input_value, bool create_variables) const
{
if (pattern.kind == BindingPattern::Kind::Object)
return generate_object_binding_pattern_bytecode(generator, pattern, initialization_mode, input_value, create_variables);
if (kind == Kind::Object)
return generate_object_binding_pattern_bytecode(generator, *this, initialization_mode, input_value, create_variables);

return generate_array_binding_pattern_bytecode(generator, pattern, initialization_mode, input_value, create_variables);
return generate_array_binding_pattern_bytecode(generator, *this, initialization_mode, input_value, create_variables);
}

static Bytecode::CodeGenerationErrorOr<void> assign_value_to_variable_declarator(Bytecode::Generator& generator, VariableDeclarator const& declarator, VariableDeclaration const& declaration, ScopedOperand value)
Expand All @@ -1487,7 +1485,7 @@ static Bytecode::CodeGenerationErrorOr<void> assign_value_to_variable_declarator
return {};
},
[&](NonnullRefPtr<BindingPattern const> const& pattern) -> Bytecode::CodeGenerationErrorOr<void> {
return generate_binding_pattern_bytecode(generator, pattern, initialization_mode, value, false);
return pattern->generate_bytecode(generator, initialization_mode, value, false);
});
}

Expand Down Expand Up @@ -2563,7 +2561,7 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> TryStatement::generate_
[&](NonnullRefPtr<BindingPattern const> const& binding_pattern) -> Bytecode::CodeGenerationErrorOr<void> {
generator.begin_variable_scope();
did_create_variable_scope_for_catch_clause = true;
TRY(generate_binding_pattern_bytecode(generator, *binding_pattern, Bytecode::Op::SetVariable::InitializationMode::Initialize, caught_value, true));
TRY(binding_pattern->generate_bytecode(generator, Bytecode::Op::SetVariable::InitializationMode::Initialize, caught_value, true));
return {};
}));

Expand Down Expand Up @@ -3076,7 +3074,7 @@ static Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> for_in_of_body_e
TRY(generator.emit_store_to_reference(**ptr, next_value));
} else {
auto& binding_pattern = lhs.get<NonnullRefPtr<BindingPattern const>>();
TRY(generate_binding_pattern_bytecode(generator, *binding_pattern, Bytecode::Op::SetVariable::InitializationMode::Set, next_value, false));
TRY(binding_pattern->generate_bytecode(generator, Bytecode::Op::SetVariable::InitializationMode::Set, next_value, false));
}
}
}
Expand Down Expand Up @@ -3161,9 +3159,8 @@ static Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> for_in_of_body_e
auto& declaration = static_cast<VariableDeclaration const&>(*lhs.get<NonnullRefPtr<ASTNode const>>());
VERIFY(declaration.declarations().size() == 1);
auto& binding_pattern = declaration.declarations().first()->target().get<NonnullRefPtr<BindingPattern const>>();
(void)TRY(generate_binding_pattern_bytecode(
(void)TRY(binding_pattern->generate_bytecode(
generator,
*binding_pattern,
head_result.lhs_kind == LHSKind::VarBinding ? Bytecode::Op::SetVariable::InitializationMode::Set : Bytecode::Op::SetVariable::InitializationMode::Initialize,
next_value,
false));
Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibJS/Bytecode/CommonImplementations.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ inline ThrowCompletionOr<void> set_variable(
return {};
}

inline Value new_function(VM& vm, FunctionExpression const& function_node, Optional<IdentifierTableIndex> const& lhs_name, Optional<Operand> const& home_object)
inline Value new_function(VM& vm, FunctionNode const& function_node, Optional<IdentifierTableIndex> const& lhs_name, Optional<Operand> const& home_object)
{
Value value;

Expand Down
Loading
Loading