Commit 1bb9fb34 authored by verwaest's avatar verwaest Committed by Commit bot

Turn AllowsLazyParsingWithoutUnresolvedVariables into a whitelist stopping at...

Turn AllowsLazyParsingWithoutUnresolvedVariables into a whitelist stopping at the outer parsed context.

Any context outer to what we're parsing already has proper context allocation, so we don't need to check those scopes.

BUG=v8:5501

Review-Url: https://codereview.chromium.org/2417643003
Cr-Commit-Position: refs/heads/master@{#40256}
parent c97535f5
......@@ -1114,14 +1114,29 @@ void DeclarationScope::AllocateVariables(ParseInfo* info, AnalyzeMode mode) {
}
}
bool Scope::AllowsLazyParsingWithoutUnresolvedVariables() const {
// If we are inside a block scope, we must find unresolved variables in the
// inner scopes to find out how to allocate variables on the block scope. At
// this point, declarations may not have yet been parsed.
for (const Scope* s = this; s != nullptr; s = s->outer_scope_) {
if (s->is_block_scope()) return false;
if (s->is_function_scope()) return false;
if (s->is_eval_scope() && is_strict(s->language_mode())) return false;
bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
const Scope* outer) const {
// If none of the outer scopes need to decide whether to context allocate
// specific variables, we can preparse inner functions without unresolved
// variables. Otherwise we need to find unresolved variables to force context
// allocation of the matching declarations. We can stop at the outer scope for
// the parse, since context allocation of those variables is already
// guaranteed to be correct.
for (const Scope* s = this; s != outer; s = s->outer_scope_) {
// Eval forces context allocation on all outer scopes, so we don't need to
// look at those scopes. Sloppy eval makes all top-level variables dynamic,
// whereas strict-mode requires context allocation.
if (s->is_eval_scope()) return !is_strict(s->language_mode());
// Catch scopes force context allocation of all variables.
if (s->is_catch_scope()) continue;
// With scopes do not introduce variables that need allocation.
if (s->is_with_scope()) continue;
// If everything is guaranteed to be context allocated we can ignore the
// scope.
if (s->has_forced_context_allocation()) continue;
// Only block scopes and function scopes should disallow preparsing.
DCHECK(s->is_block_scope() || s->is_function_scope());
return false;
}
return true;
}
......
......@@ -346,7 +346,7 @@ class Scope: public ZoneObject {
// Determine if we can parse a function literal in this scope lazily without
// caring about the unresolved variables within.
bool AllowsLazyParsingWithoutUnresolvedVariables() const;
bool AllowsLazyParsingWithoutUnresolvedVariables(const Scope* outer) const;
// The number of contexts between this and scope; zero if this == scope.
int ContextChainLength(Scope* scope) const;
......
......@@ -3924,7 +3924,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
// TODO(marja): consider lazy-parsing inner arrow functions too. is_this
// handling in Scope::ResolveVariable needs to change.
bool is_lazy_top_level_function =
can_preparse && scope()->AllowsLazyParsingWithoutUnresolvedVariables();
can_preparse && impl()->AllowsLazyParsingWithoutUnresolvedVariables();
bool should_be_used_once_hint = false;
{
FunctionState function_state(&function_state_, &scope_state_,
......
......@@ -795,10 +795,6 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
} else if (parsing_module_) {
DCHECK_EQ(outer, info->script_scope());
outer = NewModuleScope(info->script_scope());
// Never do lazy parsing in modules. If we want to support this in the
// future, we must force context-allocation for all variables that are
// declared at the module level but not MODULE-allocated.
parsing_mode = PARSE_EAGERLY;
}
DeclarationScope* scope = outer->AsDeclarationScope();
......@@ -2625,7 +2621,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
bool is_lazy_top_level_function =
can_preparse && scope()->AllowsLazyParsingWithoutUnresolvedVariables();
can_preparse && impl()->AllowsLazyParsingWithoutUnresolvedVariables();
// Determine whether we can still lazy parse the inner function.
// The preconditions are:
......
......@@ -205,6 +205,11 @@ class Parser : public ParserBase<Parser> {
friend class ParserBase<Parser>;
friend class v8::internal::ExpressionClassifier<ParserTypes<Parser>>;
bool AllowsLazyParsingWithoutUnresolvedVariables() const {
return scope()->AllowsLazyParsingWithoutUnresolvedVariables(
original_scope_);
}
// Runtime encoding of different completion modes.
enum CompletionKind {
kNormalCompletion,
......
......@@ -911,6 +911,8 @@ class PreParser : public ParserBase<PreParser> {
const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok);
bool AllowsLazyParsingWithoutUnresolvedVariables() const { return false; }
V8_INLINE LazyParsingResult SkipLazyFunctionBody(
int* materialized_literal_count, int* expected_property_count,
bool track_unresolved_variables, bool may_abort, bool* ok) {
......
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