mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 19:47:42 +00:00
LibJS/Bytecode: Skip CreateVariable for locals in "for" loop head
CreateVariable is not needed for locals because they are not stored in environment and created binding will not be used. Also if all variables in loop initialization sections are local then CreateLexicalEnvironment and LeaveLexicalEnvironment can also be ommitted.
This commit is contained in:
parent
6b191ab73d
commit
a1692931af
1 changed files with 42 additions and 22 deletions
|
@ -829,7 +829,13 @@ Bytecode::CodeGenerationErrorOr<void> ForStatement::generate_labelled_evaluation
|
|||
if (m_init->is_variable_declaration()) {
|
||||
auto& variable_declaration = verify_cast<VariableDeclaration>(*m_init);
|
||||
|
||||
if (variable_declaration.is_lexical_declaration()) {
|
||||
auto has_non_local_variables = false;
|
||||
MUST(variable_declaration.for_each_bound_identifier([&](auto const& identifier) {
|
||||
if (!identifier.is_local())
|
||||
has_non_local_variables = true;
|
||||
}));
|
||||
|
||||
if (variable_declaration.is_lexical_declaration() && has_non_local_variables) {
|
||||
has_lexical_environment = true;
|
||||
|
||||
// FIXME: Is Block correct?
|
||||
|
@ -837,8 +843,10 @@ Bytecode::CodeGenerationErrorOr<void> ForStatement::generate_labelled_evaluation
|
|||
|
||||
bool is_const = variable_declaration.is_constant_declaration();
|
||||
// NOTE: Nothing in the callback throws an exception.
|
||||
MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
|
||||
auto index = generator.intern_identifier(name);
|
||||
MUST(variable_declaration.for_each_bound_identifier([&](auto const& identifier) {
|
||||
if (identifier.is_local())
|
||||
return;
|
||||
auto index = generator.intern_identifier(identifier.string());
|
||||
generator.emit<Bytecode::Op::CreateVariable>(index, Bytecode::Op::EnvironmentMode::Lexical, is_const);
|
||||
}));
|
||||
}
|
||||
|
@ -2528,6 +2536,13 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
|||
generator.emit_set_variable(*identifier);
|
||||
}
|
||||
} else {
|
||||
auto has_non_local_variables = false;
|
||||
MUST(variable_declaration.for_each_bound_identifier([&](auto const& identifier) {
|
||||
if (!identifier.is_local())
|
||||
has_non_local_variables = true;
|
||||
}));
|
||||
|
||||
if (has_non_local_variables) {
|
||||
// 1. Let oldEnv be the running execution context's LexicalEnvironment.
|
||||
// NOTE: 'uninitializedBoundNames' refers to the lexical bindings (i.e. Const/Let) present in the second and last form.
|
||||
// 2. If uninitializedBoundNames is not an empty List, then
|
||||
|
@ -2537,14 +2552,17 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
|||
generator.begin_variable_scope();
|
||||
// c. For each String name of uninitializedBoundNames, do
|
||||
// NOTE: Nothing in the callback throws an exception.
|
||||
MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
|
||||
MUST(variable_declaration.for_each_bound_identifier([&](auto const& identifier) {
|
||||
if (identifier.is_local())
|
||||
return;
|
||||
// i. Perform ! newEnv.CreateMutableBinding(name, false).
|
||||
auto identifier = generator.intern_identifier(name);
|
||||
generator.emit<Bytecode::Op::CreateVariable>(identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
auto interned_identifier = generator.intern_identifier(identifier.string());
|
||||
generator.emit<Bytecode::Op::CreateVariable>(interned_identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
}));
|
||||
// d. Set the running execution context's LexicalEnvironment to newEnv.
|
||||
// NOTE: Done by CreateLexicalEnvironment.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Runtime Semantics: ForInOfLoopEvaluation, for any of:
|
||||
// ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
|
||||
|
@ -2691,17 +2709,19 @@ static Bytecode::CodeGenerationErrorOr<void> for_in_of_body_evaluation(Bytecode:
|
|||
auto& variable_declaration = static_cast<VariableDeclaration const&>(*lhs.get<NonnullRefPtr<ASTNode const>>());
|
||||
// 2. For each element name of the BoundNames of ForBinding, do
|
||||
// NOTE: Nothing in the callback throws an exception.
|
||||
MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
|
||||
auto identifier = generator.intern_identifier(name);
|
||||
MUST(variable_declaration.for_each_bound_identifier([&](auto const& identifier) {
|
||||
if (identifier.is_local())
|
||||
return;
|
||||
auto interned_identifier = generator.intern_identifier(identifier.string());
|
||||
// a. If IsConstantDeclaration of LetOrConst is true, then
|
||||
if (variable_declaration.is_constant_declaration()) {
|
||||
// i. Perform ! environment.CreateImmutableBinding(name, true).
|
||||
generator.emit<Bytecode::Op::CreateVariable>(identifier, Bytecode::Op::EnvironmentMode::Lexical, true);
|
||||
generator.emit<Bytecode::Op::CreateVariable>(interned_identifier, Bytecode::Op::EnvironmentMode::Lexical, true);
|
||||
}
|
||||
// b. Else,
|
||||
else {
|
||||
// i. Perform ! environment.CreateMutableBinding(name, false).
|
||||
generator.emit<Bytecode::Op::CreateVariable>(identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
generator.emit<Bytecode::Op::CreateVariable>(interned_identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
}
|
||||
}));
|
||||
// 3. Return unused.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue