[parser] Customize preparsed scope variable resolution
Otherwise preparsed variables will cause unnecessary dynamic variable allocation, which is especially bad when we're preparsing top-level functions with references to other global variables. Change-Id: I2fa17dae8c1cc5264a26ddc8b8868de1d791b0ac Reviewed-on: https://chromium-review.googlesource.com/c/1456040 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59420}
This commit is contained in:
parent
d691fde360
commit
c1119e2180
@ -2004,6 +2004,37 @@ void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
|
||||
proxy->BindTo(var);
|
||||
}
|
||||
|
||||
bool Scope::ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope,
|
||||
Scope* end) {
|
||||
// Resolve the variable in all parsed scopes to force context allocation.
|
||||
for (; scope != end; scope = scope->outer_scope_) {
|
||||
Variable* var = scope->LookupLocal(proxy->raw_name());
|
||||
if (var != nullptr) {
|
||||
var->set_is_used();
|
||||
if (!var->is_dynamic()) {
|
||||
var->ForceContextAllocation();
|
||||
if (proxy->is_assigned()) var->set_maybe_assigned();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!proxy->IsPrivateName()) return true;
|
||||
|
||||
// If we're resolving a private name, throw an exception of we didn't manage
|
||||
// to resolve. In case of eval, also look in all outer scope-info backed
|
||||
// scopes except for the script scope. Don't throw an exception if a reference
|
||||
// was found.
|
||||
Scope* start = scope;
|
||||
for (; !scope->is_script_scope(); scope = scope->outer_scope_) {
|
||||
if (scope->LookupInScopeInfo(proxy->raw_name(), start) != nullptr) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
|
||||
DCHECK(info->script_scope()->is_script_scope());
|
||||
// Lazy parsed declaration scopes are already partially analyzed. If there are
|
||||
@ -2011,9 +2042,12 @@ bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
|
||||
// scopes.
|
||||
if (WasLazilyParsed(this)) {
|
||||
DCHECK_EQ(variables_.occupancy(), 0);
|
||||
Scope* end = info->scope();
|
||||
// Resolve in all parsed scopes except for the script scope.
|
||||
if (!end->is_script_scope()) end = end->outer_scope();
|
||||
|
||||
for (VariableProxy* proxy : unresolved_list_) {
|
||||
Variable* var = Lookup<kParsedScope>(proxy, outer_scope(), nullptr);
|
||||
if (var == nullptr) {
|
||||
if (!ResolvePreparsedVariable(proxy, outer_scope(), end)) {
|
||||
info->pending_error_handler()->ReportMessageAt(
|
||||
proxy->position(), proxy->position() + 1,
|
||||
MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name(),
|
||||
@ -2021,11 +2055,6 @@ bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
|
||||
DCHECK(proxy->IsPrivateName());
|
||||
return false;
|
||||
}
|
||||
var->set_is_used();
|
||||
if (!var->is_dynamic()) {
|
||||
var->ForceContextAllocation();
|
||||
if (proxy->is_assigned()) var->set_maybe_assigned();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Resolve unresolved variables for this scope.
|
||||
|
@ -588,6 +588,8 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
static Variable* LookupSloppyEval(VariableProxy* proxy, Scope* scope,
|
||||
Scope* outer_scope_end, Scope* entry_point,
|
||||
bool force_context_allocation);
|
||||
static bool ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope,
|
||||
Scope* end);
|
||||
void ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var);
|
||||
V8_WARN_UNUSED_RESULT bool ResolveVariable(ParseInfo* info,
|
||||
VariableProxy* proxy);
|
||||
|
Loading…
Reference in New Issue
Block a user