mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 08:25:07 +00:00
LibJS: Update bytecode generator to use local variables
- Update ECMAScriptFunctionObject::function_declaration_instantiation to initialize local variables - Introduce GetLocal, SetLocal, TypeofLocal that will be used to operate on local variables. - Update bytecode generator to emit instructions for local variables
This commit is contained in:
parent
0daff637e2
commit
ae3a7fd4b8
8 changed files with 170 additions and 37 deletions
|
@ -221,7 +221,11 @@ Bytecode::CodeGenerationErrorOr<void> UnaryExpression::generate_bytecode(Bytecod
|
|||
case UnaryOp::Typeof:
|
||||
if (is<Identifier>(*m_lhs)) {
|
||||
auto& identifier = static_cast<Identifier const&>(*m_lhs);
|
||||
generator.emit<Bytecode::Op::TypeofVariable>(generator.intern_identifier(identifier.string()));
|
||||
if (identifier.is_local()) {
|
||||
generator.emit<Bytecode::Op::TypeofLocal>(identifier.local_variable_index());
|
||||
} else {
|
||||
generator.emit<Bytecode::Op::TypeofVariable>(generator.intern_identifier(identifier.string()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -291,7 +295,11 @@ Bytecode::CodeGenerationErrorOr<void> RegExpLiteral::generate_bytecode(Bytecode:
|
|||
|
||||
Bytecode::CodeGenerationErrorOr<void> Identifier::generate_bytecode(Bytecode::Generator& generator) const
|
||||
{
|
||||
generator.emit<Bytecode::Op::GetVariable>(generator.intern_identifier(m_string));
|
||||
if (is_local()) {
|
||||
generator.emit<Bytecode::Op::GetLocal>(local_variable_index());
|
||||
} else {
|
||||
generator.emit<Bytecode::Op::GetVariable>(generator.intern_identifier(m_string));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -415,7 +423,7 @@ Bytecode::CodeGenerationErrorOr<void> AssignmentExpression::generate_bytecode(By
|
|||
// e. Perform ? PutValue(lref, rval).
|
||||
if (is<Identifier>(*lhs)) {
|
||||
auto& identifier = static_cast<Identifier const&>(*lhs);
|
||||
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(identifier.string()));
|
||||
generator.emit_set_variable(identifier);
|
||||
} else if (is<MemberExpression>(*lhs)) {
|
||||
auto& expression = static_cast<MemberExpression const&>(*lhs);
|
||||
|
||||
|
@ -1043,13 +1051,15 @@ static Bytecode::CodeGenerationErrorOr<void> generate_object_binding_pattern_byt
|
|||
if (is_rest) {
|
||||
VERIFY(!initializer);
|
||||
if (name.has<NonnullRefPtr<Identifier const>>()) {
|
||||
auto identifier = name.get<NonnullRefPtr<Identifier const>>()->string();
|
||||
auto interned_identifier = generator.intern_identifier(identifier);
|
||||
auto identifier = name.get<NonnullRefPtr<Identifier const>>();
|
||||
auto interned_identifier = generator.intern_identifier(identifier->string());
|
||||
|
||||
generator.emit_with_extra_register_slots<Bytecode::Op::CopyObjectExcludingProperties>(excluded_property_names.size(), value_reg, excluded_property_names);
|
||||
if (create_variables)
|
||||
if (create_variables) {
|
||||
VERIFY(!identifier->is_local());
|
||||
generator.emit<Bytecode::Op::CreateVariable>(interned_identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
generator.emit<Bytecode::Op::SetVariable>(interned_identifier, initialization_mode);
|
||||
}
|
||||
generator.emit_set_variable(*identifier, initialization_mode);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -1126,19 +1136,19 @@ static Bytecode::CodeGenerationErrorOr<void> generate_object_binding_pattern_byt
|
|||
};
|
||||
}
|
||||
|
||||
auto& identifier = name.get<NonnullRefPtr<Identifier const>>()->string();
|
||||
auto identifier_ref = generator.intern_identifier(identifier);
|
||||
auto const& identifier = *name.get<NonnullRefPtr<Identifier const>>();
|
||||
auto identifier_ref = generator.intern_identifier(identifier.string());
|
||||
if (create_variables)
|
||||
generator.emit<Bytecode::Op::CreateVariable>(identifier_ref, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
generator.emit<Bytecode::Op::SetVariable>(identifier_ref, initialization_mode);
|
||||
generator.emit_set_variable(identifier, initialization_mode);
|
||||
} else if (alias.has<NonnullRefPtr<MemberExpression const>>()) {
|
||||
TRY(generator.emit_store_to_reference(alias.get<NonnullRefPtr<MemberExpression const>>()));
|
||||
} else {
|
||||
auto& identifier = alias.get<NonnullRefPtr<Identifier const>>()->string();
|
||||
auto identifier_ref = generator.intern_identifier(identifier);
|
||||
auto const& identifier = *alias.get<NonnullRefPtr<Identifier const>>();
|
||||
auto identifier_ref = generator.intern_identifier(identifier.string());
|
||||
if (create_variables)
|
||||
generator.emit<Bytecode::Op::CreateVariable>(identifier_ref, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
generator.emit<Bytecode::Op::SetVariable>(identifier_ref, initialization_mode);
|
||||
generator.emit_set_variable(identifier, initialization_mode);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
@ -1189,7 +1199,7 @@ static Bytecode::CodeGenerationErrorOr<void> generate_array_binding_pattern_byte
|
|||
auto interned_index = generator.intern_identifier(identifier->string());
|
||||
if (create_variables)
|
||||
generator.emit<Bytecode::Op::CreateVariable>(interned_index, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
generator.emit<Bytecode::Op::SetVariable>(interned_index, initialization_mode);
|
||||
generator.emit_set_variable(*identifier, initialization_mode);
|
||||
return {};
|
||||
},
|
||||
[&](NonnullRefPtr<BindingPattern const> const& pattern) -> Bytecode::CodeGenerationErrorOr<void> {
|
||||
|
@ -1355,7 +1365,7 @@ static Bytecode::CodeGenerationErrorOr<void> assign_accumulator_to_variable_decl
|
|||
|
||||
return declarator.target().visit(
|
||||
[&](NonnullRefPtr<Identifier const> const& id) -> Bytecode::CodeGenerationErrorOr<void> {
|
||||
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(id->string()), initialization_mode);
|
||||
generator.emit_set_variable(*id, initialization_mode);
|
||||
return {};
|
||||
},
|
||||
[&](NonnullRefPtr<BindingPattern const> const& pattern) -> Bytecode::CodeGenerationErrorOr<void> {
|
||||
|
@ -2309,7 +2319,7 @@ Bytecode::CodeGenerationErrorOr<void> ClassDeclaration::generate_bytecode(Byteco
|
|||
generator.emit<Bytecode::Op::Store>(accumulator_backup_reg);
|
||||
|
||||
TRY(m_class_expression->generate_bytecode(generator));
|
||||
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(m_class_expression.ptr()->name()), Bytecode::Op::SetVariable::InitializationMode::Initialize);
|
||||
generator.emit_set_variable(*m_class_expression.ptr()->m_name, Bytecode::Op::SetVariable::InitializationMode::Initialize);
|
||||
|
||||
generator.emit<Bytecode::Op::Load>(accumulator_backup_reg);
|
||||
return {};
|
||||
|
@ -2464,9 +2474,10 @@ 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 = 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>(binding_id);
|
||||
auto identifier = variable->target().get<NonnullRefPtr<Identifier const>>();
|
||||
auto identifier_table_ref = generator.intern_identifier(identifier->string());
|
||||
TRY(generator.emit_named_evaluation_if_anonymous_function(*variable->init(), identifier_table_ref));
|
||||
generator.emit_set_variable(*identifier);
|
||||
}
|
||||
} else {
|
||||
// 1. Let oldEnv be the running execution context's LexicalEnvironment.
|
||||
|
@ -2652,11 +2663,10 @@ static Bytecode::CodeGenerationErrorOr<void> for_in_of_body_evaluation(Bytecode:
|
|||
if (!destructuring) {
|
||||
// 1. Assert: lhs binds a single name.
|
||||
// 2. Let lhsName be the sole element of BoundNames of lhs.
|
||||
auto lhs_name = variable_declaration.declarations().first()->target().get<NonnullRefPtr<Identifier const>>()->string();
|
||||
auto lhs_name = variable_declaration.declarations().first()->target().get<NonnullRefPtr<Identifier const>>();
|
||||
// 3. Let lhsRef be ! ResolveBinding(lhsName).
|
||||
// NOTE: We're skipping all the completion stuff that the spec does, as the unwinding mechanism will take case of doing that.
|
||||
auto identifier = generator.intern_identifier(lhs_name);
|
||||
generator.emit<Bytecode::Op::SetVariable>(identifier, Bytecode::Op::SetVariable::InitializationMode::Initialize, Bytecode::Op::EnvironmentMode::Lexical);
|
||||
generator.emit_set_variable(*lhs_name, Bytecode::Op::SetVariable::InitializationMode::Initialize, Bytecode::Op::EnvironmentMode::Lexical);
|
||||
}
|
||||
}
|
||||
// i. If destructuring is false, then
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue