[parser] Only track parsing-mode (and possibly switch to the preparser) in the parser

Otherwise we could in theory abort preparsing to the preparser and preparse again before aborting again... We shouldn't have this mess; so only set up mode_ in the parser in the first place.

BUG=

Review-Url: https://codereview.chromium.org/2479213002
Cr-Commit-Position: refs/heads/master@{#40809}
This commit is contained in:
verwaest 2016-11-07 08:34:45 -08:00 committed by Commit bot
parent 21463f73e9
commit 56b8afc1c3
4 changed files with 26 additions and 32 deletions

View File

@ -198,7 +198,6 @@ class ParserBase {
fni_(nullptr), fni_(nullptr),
ast_value_factory_(ast_value_factory), ast_value_factory_(ast_value_factory),
ast_node_factory_(ast_value_factory), ast_node_factory_(ast_value_factory),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
parsing_module_(false), parsing_module_(false),
stack_limit_(stack_limit), stack_limit_(stack_limit),
zone_(zone), zone_(zone),
@ -255,8 +254,6 @@ class ParserBase {
kDontAllowRestrictedIdentifiers kDontAllowRestrictedIdentifiers
}; };
enum Mode { PARSE_LAZILY, PARSE_EAGERLY };
enum LazyParsingResult { kLazyParsingComplete, kLazyParsingAborted }; enum LazyParsingResult { kLazyParsingComplete, kLazyParsingAborted };
enum VariableDeclarationContext { enum VariableDeclarationContext {
@ -591,22 +588,6 @@ class ParserBase {
int expected_property_count_; int expected_property_count_;
}; };
class ParsingModeScope BASE_EMBEDDED {
public:
ParsingModeScope(ParserBase* parser, Mode mode)
: parser_(parser),
old_mode_(parser->mode()) {
parser_->mode_ = mode;
}
~ParsingModeScope() {
parser_->mode_ = old_mode_;
}
private:
ParserBase* parser_;
Mode old_mode_;
};
struct DeclarationDescriptor { struct DeclarationDescriptor {
enum Kind { NORMAL, PARAMETER }; enum Kind { NORMAL, PARAMETER };
Scope* scope; Scope* scope;
@ -753,7 +734,6 @@ class ParserBase {
int peek_position() const { return scanner_->peek_location().beg_pos; } int peek_position() const { return scanner_->peek_location().beg_pos; }
bool stack_overflow() const { return stack_overflow_; } bool stack_overflow() const { return stack_overflow_; }
void set_stack_overflow() { stack_overflow_ = true; } void set_stack_overflow() { stack_overflow_ = true; }
Mode mode() const { return mode_; }
INLINE(Token::Value peek()) { INLINE(Token::Value peek()) {
if (stack_overflow_) return Token::ILLEGAL; if (stack_overflow_) return Token::ILLEGAL;
@ -1440,7 +1420,6 @@ class ParserBase {
FuncNameInferrer* fni_; FuncNameInferrer* fni_;
AstValueFactory* ast_value_factory_; // Not owned. AstValueFactory* ast_value_factory_; // Not owned.
typename Types::Factory ast_node_factory_; typename Types::Factory ast_node_factory_;
Mode mode_;
bool parsing_module_; bool parsing_module_;
uintptr_t stack_limit_; uintptr_t stack_limit_;
@ -3924,7 +3903,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
FunctionKind kind = formal_parameters.scope->function_kind(); FunctionKind kind = formal_parameters.scope->function_kind();
FunctionLiteral::EagerCompileHint eager_compile_hint = FunctionLiteral::EagerCompileHint eager_compile_hint =
default_eager_compile_hint_; default_eager_compile_hint_;
bool can_preparse = mode() == PARSE_LAZILY && bool can_preparse = impl()->parse_lazily() &&
eager_compile_hint == FunctionLiteral::kShouldLazyCompile; eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
// TODO(marja): consider lazy-parsing inner arrow functions too. is_this // TODO(marja): consider lazy-parsing inner arrow functions too. is_this
// handling in Scope::ResolveVariable needs to change. // handling in Scope::ResolveVariable needs to change.
@ -4411,11 +4390,6 @@ ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token,
*ok = false; *ok = false;
return kLazyParsingComplete; return kLazyParsingComplete;
} }
// Because declarations in strict eval code don't leak into the scope
// of the eval call, it is likely that functions declared in strict
// eval code will be used within the eval code, so lazy parsing is
// probably not a win.
if (scope()->is_eval_scope()) mode_ = PARSE_EAGERLY;
} else if (impl()->IsUseAsmDirective(stat) && } else if (impl()->IsUseAsmDirective(stat) &&
token_loc.end_pos - token_loc.beg_pos == token_loc.end_pos - token_loc.beg_pos ==
sizeof("use asm") + 1) { sizeof("use asm") + 1) {

View File

@ -590,6 +590,7 @@ Parser::Parser(ParseInfo* info)
scanner_(info->unicode_cache()), scanner_(info->unicode_cache()),
reusable_preparser_(nullptr), reusable_preparser_(nullptr),
original_scope_(nullptr), original_scope_(nullptr),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
target_stack_(nullptr), target_stack_(nullptr),
compile_options_(info->compile_options()), compile_options_(info->compile_options()),
cached_parse_data_(nullptr), cached_parse_data_(nullptr),
@ -2569,11 +2570,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// parenthesis before the function means that it will be called // parenthesis before the function means that it will be called
// immediately). bar can be parsed lazily, but we need to parse it in a mode // immediately). bar can be parsed lazily, but we need to parse it in a mode
// that tracks unresolved variables. // that tracks unresolved variables.
DCHECK_IMPLIES(mode() == PARSE_LAZILY, FLAG_lazy); DCHECK_IMPLIES(parse_lazily(), FLAG_lazy);
DCHECK_IMPLIES(mode() == PARSE_LAZILY, allow_lazy()); DCHECK_IMPLIES(parse_lazily(), allow_lazy());
DCHECK_IMPLIES(mode() == PARSE_LAZILY, extension_ == nullptr); DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr);
bool can_preparse = mode() == PARSE_LAZILY && bool can_preparse = parse_lazily() &&
eager_compile_hint == FunctionLiteral::kShouldLazyCompile; eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
bool is_lazy_top_level_function = bool is_lazy_top_level_function =

View File

@ -235,6 +235,22 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
original_scope_); original_scope_);
} }
bool parse_lazily() const { return mode_ == PARSE_LAZILY; }
enum Mode { PARSE_LAZILY, PARSE_EAGERLY };
class ParsingModeScope BASE_EMBEDDED {
public:
ParsingModeScope(Parser* parser, Mode mode)
: parser_(parser), old_mode_(parser->mode_) {
parser_->mode_ = mode;
}
~ParsingModeScope() { parser_->mode_ = old_mode_; }
private:
Parser* parser_;
Mode old_mode_;
};
// Runtime encoding of different completion modes. // Runtime encoding of different completion modes.
enum CompletionKind { enum CompletionKind {
kNormalCompletion, kNormalCompletion,
@ -1119,6 +1135,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Scanner scanner_; Scanner scanner_;
PreParser* reusable_preparser_; PreParser* reusable_preparser_;
Scope* original_scope_; // for ES5 function declarations in sloppy eval Scope* original_scope_; // for ES5 function declarations in sloppy eval
Mode mode_;
friend class ParserTarget; friend class ParserTarget;
friend class ParserTargetScope; friend class ParserTargetScope;

View File

@ -911,7 +911,10 @@ class PreParser : public ParserBase<PreParser> {
const PreParserFormalParameters& parameters, FunctionKind kind, const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok); FunctionLiteral::FunctionType function_type, bool* ok);
// Indicates that we won't switch from the preparser to the preparser; we'll
// just stay where we are.
bool AllowsLazyParsingWithoutUnresolvedVariables() const { return false; } bool AllowsLazyParsingWithoutUnresolvedVariables() const { return false; }
bool parse_lazily() const { return false; }
V8_INLINE LazyParsingResult SkipFunction( V8_INLINE LazyParsingResult SkipFunction(
FunctionKind kind, DeclarationScope* function_scope, int* num_parameters, FunctionKind kind, DeclarationScope* function_scope, int* num_parameters,
@ -1523,7 +1526,6 @@ PreParserStatementList PreParser::ParseEagerFunctionBody(
PreParserIdentifier function_name, int pos, PreParserIdentifier function_name, int pos,
const PreParserFormalParameters& parameters, FunctionKind kind, const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) { FunctionLiteral::FunctionType function_type, bool* ok) {
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
PreParserStatementList result; PreParserStatementList result;
Scope* inner_scope = scope(); Scope* inner_scope = scope();