[parser] Track the correct entry-point for with/sloppy eval

This way we'll always only use the variables_ map of the first ScopeInfo-backed
Scope in the Scope chain.

Change-Id: I9187f7ef0b300b3ee36184d6dddd37242786c19a
Reviewed-on: https://chromium-review.googlesource.com/c/1340284
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57579}
This commit is contained in:
Toon Verwaest 2018-11-16 15:52:53 +01:00 committed by Commit Bot
parent 1952f92838
commit 83fd98abe9
2 changed files with 28 additions and 20 deletions

View File

@ -1808,9 +1808,8 @@ Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
// static // static
template <Scope::ScopeLookupMode mode> template <Scope::ScopeLookupMode mode>
Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope, Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
Scope* outer_scope_end, bool force_context_allocation) { Scope* outer_scope_end, Scope* entry_point,
Scope* entry_point = scope; bool force_context_allocation) {
if (mode == kDeserializedScope) { if (mode == kDeserializedScope) {
Variable* var = entry_point->variables_.Lookup(proxy->raw_name()); Variable* var = entry_point->variables_.Lookup(proxy->raw_name());
if (var != nullptr) return var; if (var != nullptr) return var;
@ -1850,12 +1849,12 @@ Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
DCHECK(!scope->is_script_scope()); DCHECK(!scope->is_script_scope());
if (V8_UNLIKELY(scope->is_with_scope())) { if (V8_UNLIKELY(scope->is_with_scope())) {
return LookupWith(proxy, scope, outer_scope_end, return LookupWith(proxy, scope, outer_scope_end, entry_point,
force_context_allocation); force_context_allocation);
} }
if (V8_UNLIKELY(scope->is_declaration_scope() && if (V8_UNLIKELY(scope->is_declaration_scope() &&
scope->AsDeclarationScope()->calls_sloppy_eval())) { scope->AsDeclarationScope()->calls_sloppy_eval())) {
return LookupSloppyEval(proxy, scope, outer_scope_end, return LookupSloppyEval(proxy, scope, outer_scope_end, entry_point,
force_context_allocation); force_context_allocation);
} }
@ -1863,7 +1862,7 @@ Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
scope = scope->outer_scope_; scope = scope->outer_scope_;
// TODO(verwaest): Separate through AnalyzePartially. // TODO(verwaest): Separate through AnalyzePartially.
if (mode == kParsedScope && !scope->scope_info_.is_null()) { if (mode == kParsedScope && !scope->scope_info_.is_null()) {
return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end); return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end, scope);
} }
} }
@ -1883,10 +1882,10 @@ Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
template Variable* Scope::Lookup<Scope::kParsedScope>( template Variable* Scope::Lookup<Scope::kParsedScope>(
VariableProxy* proxy, Scope* scope, Scope* outer_scope_end, VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
bool force_context_allocation); Scope* entry_point, bool force_context_allocation);
template Variable* Scope::Lookup<Scope::kDeserializedScope>( template Variable* Scope::Lookup<Scope::kDeserializedScope>(
VariableProxy* proxy, Scope* scope, Scope* outer_scope_end, VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
bool force_context_allocation); Scope* entry_point, bool force_context_allocation);
namespace { namespace {
bool CanBeShadowed(Scope* scope, Variable* var) { bool CanBeShadowed(Scope* scope, Variable* var) {
@ -1906,16 +1905,16 @@ bool CanBeShadowed(Scope* scope, Variable* var) {
}; // namespace }; // namespace
Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope, Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
Scope* outer_scope_end, Scope* outer_scope_end, Scope* entry_point,
bool force_context_allocation) { bool force_context_allocation) {
DCHECK(scope->is_with_scope()); DCHECK(scope->is_with_scope());
Variable* var = Variable* var =
scope->outer_scope_->scope_info_.is_null() scope->outer_scope_->scope_info_.is_null()
? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end, ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
force_context_allocation) nullptr, force_context_allocation)
: Lookup<kDeserializedScope>(proxy, scope->outer_scope_, : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
outer_scope_end); outer_scope_end, entry_point);
if (!CanBeShadowed(scope, var)) return var; if (!CanBeShadowed(scope, var)) return var;
@ -1931,21 +1930,26 @@ Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
var->ForceContextAllocation(); var->ForceContextAllocation();
if (proxy->is_assigned()) var->set_maybe_assigned(); if (proxy->is_assigned()) var->set_maybe_assigned();
} }
return scope->NonLocal(proxy->raw_name(), VariableMode::kDynamic); if (entry_point != nullptr) entry_point->variables_.Remove(var);
Scope* target = entry_point == nullptr ? scope : entry_point;
return target->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
} }
Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope, Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
Scope* outer_scope_end, Scope* outer_scope_end, Scope* entry_point,
bool force_context_allocation) { bool force_context_allocation) {
DCHECK(scope->is_declaration_scope() && DCHECK(scope->is_declaration_scope() &&
scope->AsDeclarationScope()->calls_sloppy_eval()); scope->AsDeclarationScope()->calls_sloppy_eval());
// If we're compiling eval, it's possible that the outer scope is the first
// ScopeInfo-backed scope.
Scope* entry = entry_point == nullptr ? scope->outer_scope_ : entry_point;
Variable* var = Variable* var =
scope->outer_scope_->scope_info_.is_null() scope->outer_scope_->scope_info_.is_null()
? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end, ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
force_context_allocation) nullptr, force_context_allocation)
: Lookup<kDeserializedScope>(proxy, scope->outer_scope_, : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
outer_scope_end); outer_scope_end, entry);
if (!CanBeShadowed(scope, var)) return var; if (!CanBeShadowed(scope, var)) return var;
// A variable binding may have been found in an outer scope, but the current // A variable binding may have been found in an outer scope, but the current
@ -1956,13 +1960,17 @@ Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
// here (this excludes block and catch scopes), and variable lookups at // here (this excludes block and catch scopes), and variable lookups at
// script scope are always dynamic. // script scope are always dynamic.
if (var->IsGlobalObjectProperty()) { if (var->IsGlobalObjectProperty()) {
return scope->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal); Scope* target = entry_point == nullptr ? scope : entry_point;
return target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
} }
if (var->is_dynamic()) return var; if (var->is_dynamic()) return var;
Variable* invalidated = var; Variable* invalidated = var;
var = scope->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal); if (entry_point != nullptr) entry_point->variables_.Remove(invalidated);
Scope* target = entry_point == nullptr ? scope : entry_point;
var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
var->set_local_if_not_shadowed(invalidated); var->set_local_if_not_shadowed(invalidated);
return var; return var;

View File

@ -615,13 +615,13 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// calling context of 'eval'. // calling context of 'eval'.
template <ScopeLookupMode mode> template <ScopeLookupMode mode>
static Variable* Lookup(VariableProxy* proxy, Scope* scope, static Variable* Lookup(VariableProxy* proxy, Scope* scope,
Scope* outer_scope_end, Scope* outer_scope_end, Scope* entry_point = nullptr,
bool force_context_allocation = false); bool force_context_allocation = false);
static Variable* LookupWith(VariableProxy* proxy, Scope* scope, static Variable* LookupWith(VariableProxy* proxy, Scope* scope,
Scope* outer_scope_end, Scope* outer_scope_end, Scope* entry_point,
bool force_context_allocation); bool force_context_allocation);
static Variable* LookupSloppyEval(VariableProxy* proxy, Scope* scope, static Variable* LookupSloppyEval(VariableProxy* proxy, Scope* scope,
Scope* outer_scope_end, Scope* outer_scope_end, Scope* entry_point,
bool force_context_allocation); bool force_context_allocation);
void ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var); void ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var);
V8_WARN_UNUSED_RESULT bool ResolveVariable(ParseInfo* info, V8_WARN_UNUSED_RESULT bool ResolveVariable(ParseInfo* info,