mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:38:12 +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,22 +2536,32 @@ static Bytecode::CodeGenerationErrorOr<ForInOfHeadEvaluationResult> for_in_of_he
|
|||
generator.emit_set_variable(*identifier);
|
||||
}
|
||||
} else {
|
||||
// 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
|
||||
entered_lexical_scope = true;
|
||||
// a. Assert: uninitializedBoundNames has no duplicate entries.
|
||||
// b. Let newEnv be NewDeclarativeEnvironment(oldEnv).
|
||||
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) {
|
||||
// i. Perform ! newEnv.CreateMutableBinding(name, false).
|
||||
auto identifier = generator.intern_identifier(name);
|
||||
generator.emit<Bytecode::Op::CreateVariable>(identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
|
||||
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;
|
||||
}));
|
||||
// d. Set the running execution context's LexicalEnvironment to newEnv.
|
||||
// NOTE: Done by CreateLexicalEnvironment.
|
||||
|
||||
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
|
||||
entered_lexical_scope = true;
|
||||
// a. Assert: uninitializedBoundNames has no duplicate entries.
|
||||
// b. Let newEnv be NewDeclarativeEnvironment(oldEnv).
|
||||
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_identifier([&](auto const& identifier) {
|
||||
if (identifier.is_local())
|
||||
return;
|
||||
// i. Perform ! newEnv.CreateMutableBinding(name, 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:
|
||||
|
@ -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