Commit c70001ae authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Separate sloppy-eval var-conflict detection from the rest

This allows us to do fewer checks on the common path.

Change-Id: I2d1a9239cbf7b637bdbc2a15abaadae225410acf
Reviewed-on: https://chromium-review.googlesource.com/c/1430700Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59078}
parent 008478ee
......@@ -1139,37 +1139,55 @@ Variable* Scope::NewTemporary(const AstRawString* name,
}
Declaration* Scope::CheckConflictingVarDeclarations() {
bool is_sloppy_eval = is_eval_scope() && is_sloppy(language_mode());
// In case of a regular function/script, check all scopes except for the scope
// in which the var ends up being declared.
Scope* end = this;
// In the case of eval, check all scopes up to and including the next
// declaration scope.
if (is_sloppy_eval) {
while (end->is_eval_scope()) end = end->outer_scope_->GetDeclarationScope();
end = end->outer_scope_;
}
for (Declaration* decl : decls_) {
// Lexical vs lexical conflicts within the same scope have already been
// captured in Parser::Declare. The only conflicts we still need to check
// are lexical vs nested var.
Scope* current = nullptr;
if (decl->IsVariableDeclaration() &&
decl->AsVariableDeclaration()->AsNested() != nullptr) {
current = decl->AsVariableDeclaration()->AsNested()->scope();
} else if (is_sloppy_eval) {
if (IsLexicalVariableMode(decl->var()->mode())) continue;
current = outer_scope_;
Scope* current = decl->AsVariableDeclaration()->AsNested()->scope();
DCHECK(decl->var()->mode() == VariableMode::kVar ||
decl->var()->mode() == VariableMode::kDynamic);
// Iterate through all scopes until the declaration scope.
do {
// There is a conflict if there exists a non-VAR binding.
if (current->is_catch_scope()) {
current = current->outer_scope();
continue;
}
Variable* other_var = current->LookupLocal(decl->var()->raw_name());
if (other_var != nullptr) {
DCHECK(IsLexicalVariableMode(other_var->mode()));
return decl;
}
current = current->outer_scope();
} while (current != this);
}
if (current == nullptr) continue;
DCHECK(decl->var()->mode() == VariableMode::kVar ||
decl->var()->mode() == VariableMode::kDynamic);
}
if (V8_LIKELY(!is_eval_scope())) return nullptr;
if (!is_sloppy(language_mode())) return nullptr;
// Var declarations in sloppy eval are hoisted to the first non-eval
// declaration scope. Check for conflicts between the eval scope that
// declaration scope.
Scope* end = this;
do {
end = end->outer_scope_->GetDeclarationScope();
} while (end->is_eval_scope());
end = end->outer_scope_;
for (Declaration* decl : decls_) {
if (IsLexicalVariableMode(decl->var()->mode())) continue;
Scope* current = outer_scope_;
// Iterate through all scopes until and including the declaration scope.
do {
// There is a conflict if there exists a non-VAR binding.
// There is a conflict if there exists a non-VAR binding up to the
// declaration scope in which this sloppy-eval runs.
Variable* other_var =
current->LookupInScopeOrScopeInfo(decl->var()->raw_name());
if (other_var != nullptr && IsLexicalVariableMode(other_var->mode())) {
DCHECK(!current->is_catch_scope());
return decl;
}
current = current->outer_scope();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment