mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibJS: Use the IdentifierTable for NewFunction and NewClass lhs names
This makes them trivially copyable, which is an assumption multiple optimizations use when rebuilding the instruction stream. This fixes most optimized crashes in the test262 suite.
This commit is contained in:
parent
c21255da7f
commit
37067cf3ca
Notes:
sideshowbarker
2024-07-17 05:02:35 +09:00
Author: https://github.com/Hendiadyoin1 Commit: https://github.com/SerenityOS/serenity/commit/37067cf3ca Pull-request: https://github.com/SerenityOS/serenity/pull/19692 Issue: https://github.com/SerenityOS/serenity/issues/19690
6 changed files with 32 additions and 28 deletions
|
@ -16,6 +16,7 @@
|
|||
#include <AK/Variant.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibJS/Bytecode/CodeGenerationError.h>
|
||||
#include <LibJS/Bytecode/IdentifierTable.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Heap/Handle.h>
|
||||
#include <LibJS/Runtime/ClassFieldDefinition.h>
|
||||
|
@ -738,7 +739,7 @@ public:
|
|||
virtual void dump(int indent) const override;
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode(Bytecode::Generator&) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<DeprecatedFlyString const&> lhs_name) const;
|
||||
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name) const;
|
||||
|
||||
bool has_name() const { return !name().is_empty(); }
|
||||
|
||||
|
@ -1421,7 +1422,7 @@ public:
|
|||
virtual Completion execute(Interpreter&) const override;
|
||||
virtual void dump(int indent) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode(Bytecode::Generator&) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<DeprecatedFlyString const&> lhs_name) const;
|
||||
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name) const;
|
||||
|
||||
bool has_name() const { return !m_name.is_empty(); }
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ Bytecode::CodeGenerationErrorOr<void> AssignmentExpression::generate_bytecode(By
|
|||
// i. Let rref be the result of evaluating AssignmentExpression.
|
||||
// ii. Let rval be ? GetValue(rref).
|
||||
if (lhs->is_identifier()) {
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*m_rhs, static_cast<Identifier const&>(*lhs).string()));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*m_rhs, generator.intern_identifier(static_cast<Identifier const&>(*lhs).string())));
|
||||
} else {
|
||||
TRY(m_rhs->generate_bytecode(generator));
|
||||
}
|
||||
|
@ -495,7 +495,7 @@ Bytecode::CodeGenerationErrorOr<void> AssignmentExpression::generate_bytecode(By
|
|||
generator.emit<Bytecode::Op::Store>(lhs_reg);
|
||||
|
||||
if (lhs->is_identifier())
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*m_rhs, static_cast<Identifier const&>(*lhs).string()));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*m_rhs, generator.intern_identifier(static_cast<Identifier const&>(*lhs).string())));
|
||||
else
|
||||
TRY(m_rhs->generate_bytecode(generator));
|
||||
|
||||
|
@ -907,7 +907,7 @@ Bytecode::CodeGenerationErrorOr<void> ObjectExpression::generate_bytecode(Byteco
|
|||
if (property_kind == Bytecode::Op::PropertyKind::ProtoSetter) {
|
||||
TRY(property->value().generate_bytecode(generator));
|
||||
} else if (property_kind != Bytecode::Op::PropertyKind::Spread) {
|
||||
DeprecatedFlyString name = string_literal.value();
|
||||
auto name = generator.intern_identifier(string_literal.value());
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(property->value(), name));
|
||||
}
|
||||
|
||||
|
@ -994,7 +994,7 @@ Bytecode::CodeGenerationErrorOr<void> FunctionDeclaration::generate_bytecode(Byt
|
|||
return {};
|
||||
}
|
||||
|
||||
Bytecode::CodeGenerationErrorOr<void> FunctionExpression::generate_bytecode_with_lhs_name(Bytecode::Generator& generator, Optional<DeprecatedFlyString const&> lhs_name) const
|
||||
Bytecode::CodeGenerationErrorOr<void> FunctionExpression::generate_bytecode_with_lhs_name(Bytecode::Generator& generator, Optional<Bytecode::IdentifierTableIndex> lhs_name) const
|
||||
{
|
||||
bool has_name = !name().is_empty();
|
||||
Optional<Bytecode::IdentifierTableIndex> name_identifier;
|
||||
|
@ -1085,9 +1085,9 @@ static Bytecode::CodeGenerationErrorOr<void> generate_object_binding_pattern_byt
|
|||
|
||||
generator.switch_to_basic_block(if_undefined_block);
|
||||
if (auto const* alias_identifier = alias.get_pointer<NonnullRefPtr<Identifier const>>()) {
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*initializer, (*alias_identifier)->string()));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*initializer, generator.intern_identifier((*alias_identifier)->string())));
|
||||
} else if (auto const* lhs = name.get_pointer<NonnullRefPtr<Identifier const>>()) {
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*initializer, (*lhs)->string()));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*initializer, generator.intern_identifier((*lhs)->string())));
|
||||
} else {
|
||||
TRY(initializer->generate_bytecode(generator));
|
||||
}
|
||||
|
@ -1294,9 +1294,9 @@ static Bytecode::CodeGenerationErrorOr<void> generate_array_binding_pattern_byte
|
|||
generator.switch_to_basic_block(value_is_undefined_block);
|
||||
|
||||
if (auto const* alias_identifier = alias.get_pointer<NonnullRefPtr<Identifier const>>()) {
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*initializer, (*alias_identifier)->string()));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*initializer, generator.intern_identifier((*alias_identifier)->string())));
|
||||
} else if (auto const* name_identifier = name.get_pointer<NonnullRefPtr<Identifier const>>()) {
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*initializer, (*name_identifier)->string()));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*initializer, generator.intern_identifier((*name_identifier)->string())));
|
||||
} else {
|
||||
TRY(initializer->generate_bytecode(generator));
|
||||
}
|
||||
|
@ -1356,7 +1356,7 @@ Bytecode::CodeGenerationErrorOr<void> VariableDeclaration::generate_bytecode(Byt
|
|||
for (auto& declarator : m_declarations) {
|
||||
if (declarator->init()) {
|
||||
if (auto const* lhs = declarator->target().get_pointer<NonnullRefPtr<Identifier const>>()) {
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*declarator->init(), (*lhs)->string()));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*declarator->init(), generator.intern_identifier((*lhs)->string())));
|
||||
} else {
|
||||
TRY(declarator->init()->generate_bytecode(generator));
|
||||
}
|
||||
|
@ -2273,7 +2273,7 @@ Bytecode::CodeGenerationErrorOr<void> ClassDeclaration::generate_bytecode(Byteco
|
|||
return {};
|
||||
}
|
||||
|
||||
Bytecode::CodeGenerationErrorOr<void> ClassExpression::generate_bytecode_with_lhs_name(Bytecode::Generator& generator, Optional<DeprecatedFlyString const&> lhs_name) const
|
||||
Bytecode::CodeGenerationErrorOr<void> ClassExpression::generate_bytecode_with_lhs_name(Bytecode::Generator& generator, Optional<Bytecode::IdentifierTableIndex> lhs_name) const
|
||||
{
|
||||
generator.emit<Bytecode::Op::NewClass>(*this, lhs_name);
|
||||
return {};
|
||||
|
@ -2405,9 +2405,9 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
|||
auto& variable = variable_declaration.declarations().first();
|
||||
if (variable->init()) {
|
||||
VERIFY(variable->target().has<NonnullRefPtr<Identifier const>>());
|
||||
auto& binding_id = variable->target().get<NonnullRefPtr<Identifier const>>()->string();
|
||||
auto binding_id = generator.intern_identifier(variable->target().get<NonnullRefPtr<Identifier const>>()->string());
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*variable->init(), binding_id));
|
||||
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(binding_id));
|
||||
generator.emit<Bytecode::Op::SetVariable>(binding_id);
|
||||
}
|
||||
} else {
|
||||
// 1. Let oldEnv be the running execution context's LexicalEnvironment.
|
||||
|
@ -2751,7 +2751,7 @@ Bytecode::CodeGenerationErrorOr<void> MetaProperty::generate_bytecode(Bytecode::
|
|||
|
||||
Bytecode::CodeGenerationErrorOr<void> ClassFieldInitializerStatement::generate_bytecode(Bytecode::Generator& generator) const
|
||||
{
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*m_expression, m_class_field_identifier_name));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*m_expression, generator.intern_identifier(m_class_field_identifier_name)));
|
||||
generator.perform_needed_unwinds<Bytecode::Op::Return>();
|
||||
generator.emit<Bytecode::Op::Return>();
|
||||
return {};
|
||||
|
@ -2881,7 +2881,7 @@ Bytecode::CodeGenerationErrorOr<void> ExportStatement::generate_bytecode(Bytecod
|
|||
|
||||
// ExportDeclaration : export default AssignmentExpression ;
|
||||
VERIFY(is<Expression>(*m_statement));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(static_cast<Expression const&>(*m_statement), DeprecatedFlyString("default"sv)));
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(static_cast<Expression const&>(*m_statement), generator.intern_identifier("default"sv)));
|
||||
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(ExportStatement::local_name_for_default), Bytecode::Op::SetVariable::InitializationMode::Initialize);
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -452,7 +452,7 @@ void Generator::pop_home_object()
|
|||
m_home_objects.take_last();
|
||||
}
|
||||
|
||||
void Generator::emit_new_function(FunctionExpression const& function_node, Optional<DeprecatedFlyString const&> lhs_name)
|
||||
void Generator::emit_new_function(FunctionExpression const& function_node, Optional<IdentifierTableIndex> lhs_name)
|
||||
{
|
||||
if (m_home_objects.is_empty())
|
||||
emit<Op::NewFunction>(function_node, lhs_name);
|
||||
|
@ -460,7 +460,7 @@ void Generator::emit_new_function(FunctionExpression const& function_node, Optio
|
|||
emit<Op::NewFunction>(function_node, lhs_name, m_home_objects.last());
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<void> Generator::emit_named_evaluation_if_anonymous_function(Expression const& expression, Optional<DeprecatedFlyString const&> lhs_name)
|
||||
CodeGenerationErrorOr<void> Generator::emit_named_evaluation_if_anonymous_function(Expression const& expression, Optional<IdentifierTableIndex> lhs_name)
|
||||
{
|
||||
if (is<FunctionExpression>(expression)) {
|
||||
auto const& function_expression = static_cast<FunctionExpression const&>(expression);
|
||||
|
|
|
@ -85,9 +85,9 @@ public:
|
|||
|
||||
void push_home_object(Register);
|
||||
void pop_home_object();
|
||||
void emit_new_function(JS::FunctionExpression const&, Optional<DeprecatedFlyString const&> lhs_name);
|
||||
void emit_new_function(JS::FunctionExpression const&, Optional<IdentifierTableIndex> lhs_name);
|
||||
|
||||
CodeGenerationErrorOr<void> emit_named_evaluation_if_anonymous_function(Expression const&, Optional<DeprecatedFlyString const&> lhs_name);
|
||||
CodeGenerationErrorOr<void> emit_named_evaluation_if_anonymous_function(Expression const&, Optional<IdentifierTableIndex> lhs_name);
|
||||
|
||||
void begin_continuable_scope(Label continue_target, Vector<DeprecatedFlyString> const& language_label_set);
|
||||
void end_continuable_scope();
|
||||
|
|
|
@ -795,7 +795,10 @@ ThrowCompletionOr<void> NewFunction::execute_impl(Bytecode::Interpreter& interpr
|
|||
auto& vm = interpreter.vm();
|
||||
|
||||
if (!m_function_node.has_name()) {
|
||||
interpreter.accumulator() = m_function_node.instantiate_ordinary_function_expression(vm, m_lhs_name.value_or({}));
|
||||
DeprecatedFlyString name = {};
|
||||
if (m_lhs_name.has_value())
|
||||
name = interpreter.current_executable().get_identifier(m_lhs_name.value());
|
||||
interpreter.accumulator() = m_function_node.instantiate_ordinary_function_expression(vm, name);
|
||||
} else {
|
||||
interpreter.accumulator() = ECMAScriptFunctionObject::create(interpreter.realm(), m_function_node.name(), m_function_node.source_text(), m_function_node.body(), m_function_node.parameters(), m_function_node.function_length(), vm.lexical_environment(), vm.running_execution_context().private_environment, m_function_node.kind(), m_function_node.is_strict_mode(), m_function_node.might_need_arguments_object(), m_function_node.contains_direct_call_to_eval(), m_function_node.is_arrow_function());
|
||||
}
|
||||
|
@ -1149,7 +1152,7 @@ ThrowCompletionOr<void> NewClass::execute_impl(Bytecode::Interpreter& interprete
|
|||
ECMAScriptFunctionObject* class_object = nullptr;
|
||||
|
||||
if (!m_class_expression.has_name() && m_lhs_name.has_value())
|
||||
class_object = TRY(m_class_expression.class_definition_evaluation(vm, {}, m_lhs_name.value()));
|
||||
class_object = TRY(m_class_expression.class_definition_evaluation(vm, {}, interpreter.current_executable().get_identifier(m_lhs_name.value())));
|
||||
else
|
||||
class_object = TRY(m_class_expression.class_definition_evaluation(vm, name, name.is_null() ? ""sv : name));
|
||||
|
||||
|
|
|
@ -822,10 +822,10 @@ private:
|
|||
|
||||
class NewClass final : public Instruction {
|
||||
public:
|
||||
explicit NewClass(ClassExpression const& class_expression, Optional<DeprecatedFlyString const&> lhs_name)
|
||||
explicit NewClass(ClassExpression const& class_expression, Optional<IdentifierTableIndex> lhs_name)
|
||||
: Instruction(Type::NewClass)
|
||||
, m_class_expression(class_expression)
|
||||
, m_lhs_name(lhs_name.has_value() ? *lhs_name : Optional<DeprecatedFlyString> {})
|
||||
, m_lhs_name(lhs_name)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -836,15 +836,15 @@ public:
|
|||
|
||||
private:
|
||||
ClassExpression const& m_class_expression;
|
||||
Optional<DeprecatedFlyString> m_lhs_name;
|
||||
Optional<IdentifierTableIndex> m_lhs_name;
|
||||
};
|
||||
|
||||
class NewFunction final : public Instruction {
|
||||
public:
|
||||
explicit NewFunction(FunctionExpression const& function_node, Optional<DeprecatedFlyString const&> lhs_name, Optional<Register> home_object = {})
|
||||
explicit NewFunction(FunctionExpression const& function_node, Optional<IdentifierTableIndex> lhs_name, Optional<Register> home_object = {})
|
||||
: Instruction(Type::NewFunction)
|
||||
, m_function_node(function_node)
|
||||
, m_lhs_name(lhs_name.has_value() ? *lhs_name : Optional<DeprecatedFlyString> {})
|
||||
, m_lhs_name(lhs_name)
|
||||
, m_home_object(move(home_object))
|
||||
{
|
||||
}
|
||||
|
@ -856,7 +856,7 @@ public:
|
|||
|
||||
private:
|
||||
FunctionExpression const& m_function_node;
|
||||
Optional<DeprecatedFlyString> m_lhs_name;
|
||||
Optional<IdentifierTableIndex> m_lhs_name;
|
||||
Optional<Register> m_home_object;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue