| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index 9f18790eefce3cc4ff1a4637f29cd039e5b84262..78791ec905d48196e233de3be60258d67fdf262c 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -231,41 +231,39 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
|
| // 'continue' statement targets). Upon construction, a new target is
|
| // added; it is removed upon destruction.
|
|
|
| -class Target BASE_EMBEDDED {
|
| +class ParserTarget BASE_EMBEDDED {
|
| public:
|
| - Target(Target** variable, BreakableStatement* statement)
|
| - : variable_(variable), statement_(statement), previous_(*variable) {
|
| - *variable = this;
|
| + ParserTarget(ParserBase<Parser>* parser, BreakableStatement* statement)
|
| + : variable_(&parser->impl()->target_stack_),
|
| + statement_(statement),
|
| + previous_(parser->impl()->target_stack_) {
|
| + parser->impl()->target_stack_ = this;
|
| }
|
|
|
| - ~Target() {
|
| - *variable_ = previous_;
|
| - }
|
| + ~ParserTarget() { *variable_ = previous_; }
|
|
|
| - Target* previous() { return previous_; }
|
| + ParserTarget* previous() { return previous_; }
|
| BreakableStatement* statement() { return statement_; }
|
|
|
| private:
|
| - Target** variable_;
|
| + ParserTarget** variable_;
|
| BreakableStatement* statement_;
|
| - Target* previous_;
|
| + ParserTarget* previous_;
|
| };
|
|
|
| -
|
| -class TargetScope BASE_EMBEDDED {
|
| +class ParserTargetScope BASE_EMBEDDED {
|
| public:
|
| - explicit TargetScope(Target** variable)
|
| - : variable_(variable), previous_(*variable) {
|
| - *variable = NULL;
|
| + explicit ParserTargetScope(ParserBase<Parser>* parser)
|
| + : variable_(&parser->impl()->target_stack_),
|
| + previous_(parser->impl()->target_stack_) {
|
| + parser->impl()->target_stack_ = nullptr;
|
| }
|
|
|
| - ~TargetScope() {
|
| - *variable_ = previous_;
|
| - }
|
| + ~ParserTargetScope() { *variable_ = previous_; }
|
|
|
| private:
|
| - Target** variable_;
|
| - Target* previous_;
|
| + ParserTarget** variable_;
|
| + ParserTarget* previous_;
|
| };
|
|
|
|
|
| @@ -931,131 +929,6 @@ FunctionLiteral* Parser::DoParseLazy(ParseInfo* info,
|
| return result;
|
| }
|
|
|
| -
|
| -void Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
|
| - bool* ok) {
|
| - // StatementList ::
|
| - // (StatementListItem)* <end_token>
|
| -
|
| - // Allocate a target stack to use for this set of source
|
| - // elements. This way, all scripts and functions get their own
|
| - // target stack thus avoiding illegal breaks and continues across
|
| - // functions.
|
| - TargetScope scope(&this->target_stack_);
|
| -
|
| - DCHECK(body != NULL);
|
| - bool directive_prologue = true; // Parsing directive prologue.
|
| -
|
| - while (peek() != end_token) {
|
| - if (directive_prologue && peek() != Token::STRING) {
|
| - directive_prologue = false;
|
| - }
|
| -
|
| - Scanner::Location token_loc = scanner()->peek_location();
|
| - Statement* stat = ParseStatementListItem(CHECK_OK_VOID);
|
| - if (stat == NULL || stat->IsEmpty()) {
|
| - directive_prologue = false; // End of directive prologue.
|
| - continue;
|
| - }
|
| -
|
| - if (directive_prologue) {
|
| - // A shot at a directive.
|
| - ExpressionStatement* e_stat;
|
| - Literal* literal;
|
| - // Still processing directive prologue?
|
| - if ((e_stat = stat->AsExpressionStatement()) != NULL &&
|
| - (literal = e_stat->expression()->AsLiteral()) != NULL &&
|
| - literal->raw_value()->IsString()) {
|
| - // Check "use strict" directive (ES5 14.1), "use asm" directive.
|
| - bool use_strict_found =
|
| - literal->raw_value()->AsString() ==
|
| - ast_value_factory()->use_strict_string() &&
|
| - token_loc.end_pos - token_loc.beg_pos ==
|
| - ast_value_factory()->use_strict_string()->length() + 2;
|
| - if (use_strict_found) {
|
| - if (is_sloppy(language_mode())) {
|
| - RaiseLanguageMode(STRICT);
|
| - }
|
| -
|
| - if (!this->scope()->HasSimpleParameters()) {
|
| - // TC39 deemed "use strict" directives to be an error when occurring
|
| - // in the body of a function with non-simple parameter list, on
|
| - // 29/7/2015. https://goo.gl/ueA7Ln
|
| - const AstRawString* string = literal->raw_value()->AsString();
|
| - ReportMessageAt(token_loc,
|
| - MessageTemplate::kIllegalLanguageModeDirective,
|
| - string);
|
| - *ok = false;
|
| - return;
|
| - }
|
| - // 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 (this->scope()->is_eval_scope()) mode_ = PARSE_EAGERLY;
|
| - } else if (literal->raw_value()->AsString() ==
|
| - ast_value_factory()->use_asm_string() &&
|
| - token_loc.end_pos - token_loc.beg_pos ==
|
| - ast_value_factory()->use_asm_string()->length() + 2) {
|
| - // Store the usage count; The actual use counter on the isolate is
|
| - // incremented after parsing is done.
|
| - ++use_counts_[v8::Isolate::kUseAsm];
|
| - DCHECK(this->scope()->is_declaration_scope());
|
| - this->scope()->AsDeclarationScope()->set_asm_module();
|
| - } else {
|
| - // Should not change mode, but will increment UseCounter
|
| - // if appropriate. Ditto usages below.
|
| - RaiseLanguageMode(SLOPPY);
|
| - }
|
| - } else {
|
| - // End of the directive prologue.
|
| - directive_prologue = false;
|
| - RaiseLanguageMode(SLOPPY);
|
| - }
|
| - } else {
|
| - RaiseLanguageMode(SLOPPY);
|
| - }
|
| -
|
| - body->Add(stat, zone());
|
| - }
|
| -}
|
| -
|
| -
|
| -Statement* Parser::ParseStatementListItem(bool* ok) {
|
| - // (Ecma 262 6th Edition, 13.1):
|
| - // StatementListItem:
|
| - // Statement
|
| - // Declaration
|
| - const Token::Value peeked = peek();
|
| - switch (peeked) {
|
| - case Token::FUNCTION:
|
| - return ParseHoistableDeclaration(NULL, false, ok);
|
| - case Token::CLASS:
|
| - Consume(Token::CLASS);
|
| - return ParseClassDeclaration(NULL, false, ok);
|
| - case Token::CONST:
|
| - return ParseVariableStatement(kStatementListItem, NULL, ok);
|
| - case Token::VAR:
|
| - return ParseVariableStatement(kStatementListItem, NULL, ok);
|
| - case Token::LET:
|
| - if (IsNextLetKeyword()) {
|
| - return ParseVariableStatement(kStatementListItem, NULL, ok);
|
| - }
|
| - break;
|
| - case Token::ASYNC:
|
| - if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
|
| - !scanner()->HasAnyLineTerminatorAfterNext()) {
|
| - Consume(Token::ASYNC);
|
| - return ParseAsyncFunctionDeclaration(NULL, false, ok);
|
| - }
|
| - /* falls through */
|
| - default:
|
| - break;
|
| - }
|
| - return ParseStatement(NULL, kAllowLabelledFunctionStatement, ok);
|
| -}
|
| -
|
| -
|
| Statement* Parser::ParseModuleItem(bool* ok) {
|
| // ecma262/#prod-ModuleItem
|
| // ModuleItem :
|
| @@ -1486,139 +1359,6 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
| return result;
|
| }
|
|
|
| -Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
|
| - AllowLabelledFunctionStatement allow_function,
|
| - bool* ok) {
|
| - // Statement ::
|
| - // EmptyStatement
|
| - // ...
|
| -
|
| - if (peek() == Token::SEMICOLON) {
|
| - Next();
|
| - return factory()->NewEmptyStatement(kNoSourcePosition);
|
| - }
|
| - return ParseSubStatement(labels, allow_function, ok);
|
| -}
|
| -
|
| -Statement* Parser::ParseSubStatement(
|
| - ZoneList<const AstRawString*>* labels,
|
| - AllowLabelledFunctionStatement allow_function, bool* ok) {
|
| - // Statement ::
|
| - // Block
|
| - // VariableStatement
|
| - // EmptyStatement
|
| - // ExpressionStatement
|
| - // IfStatement
|
| - // IterationStatement
|
| - // ContinueStatement
|
| - // BreakStatement
|
| - // ReturnStatement
|
| - // WithStatement
|
| - // LabelledStatement
|
| - // SwitchStatement
|
| - // ThrowStatement
|
| - // TryStatement
|
| - // DebuggerStatement
|
| -
|
| - // Note: Since labels can only be used by 'break' and 'continue'
|
| - // statements, which themselves are only valid within blocks,
|
| - // iterations or 'switch' statements (i.e., BreakableStatements),
|
| - // labels can be simply ignored in all other cases; except for
|
| - // trivial labeled break statements 'label: break label' which is
|
| - // parsed into an empty statement.
|
| - switch (peek()) {
|
| - case Token::LBRACE:
|
| - return ParseBlock(labels, ok);
|
| -
|
| - case Token::SEMICOLON:
|
| - Next();
|
| - return factory()->NewEmptyStatement(kNoSourcePosition);
|
| -
|
| - case Token::IF:
|
| - return ParseIfStatement(labels, ok);
|
| -
|
| - case Token::DO:
|
| - return ParseDoWhileStatement(labels, ok);
|
| -
|
| - case Token::WHILE:
|
| - return ParseWhileStatement(labels, ok);
|
| -
|
| - case Token::FOR:
|
| - return ParseForStatement(labels, ok);
|
| -
|
| - case Token::CONTINUE:
|
| - case Token::BREAK:
|
| - case Token::RETURN:
|
| - case Token::THROW:
|
| - case Token::TRY: {
|
| - // These statements must have their labels preserved in an enclosing
|
| - // block
|
| - if (labels == NULL) {
|
| - return ParseStatementAsUnlabelled(labels, ok);
|
| - } else {
|
| - Block* result =
|
| - factory()->NewBlock(labels, 1, false, kNoSourcePosition);
|
| - Target target(&this->target_stack_, result);
|
| - Statement* statement = ParseStatementAsUnlabelled(labels, CHECK_OK);
|
| - if (result) result->statements()->Add(statement, zone());
|
| - return result;
|
| - }
|
| - }
|
| -
|
| - case Token::WITH:
|
| - return ParseWithStatement(labels, ok);
|
| -
|
| - case Token::SWITCH:
|
| - return ParseSwitchStatement(labels, ok);
|
| -
|
| - case Token::FUNCTION:
|
| - // FunctionDeclaration only allowed as a StatementListItem, not in
|
| - // an arbitrary Statement position. Exceptions such as
|
| - // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
|
| - // are handled by calling ParseScopedStatement rather than
|
| - // ParseSubStatement directly.
|
| - ReportMessageAt(scanner()->peek_location(),
|
| - is_strict(language_mode())
|
| - ? MessageTemplate::kStrictFunction
|
| - : MessageTemplate::kSloppyFunction);
|
| - *ok = false;
|
| - return nullptr;
|
| -
|
| - case Token::DEBUGGER:
|
| - return ParseDebuggerStatement(ok);
|
| -
|
| - case Token::VAR:
|
| - return ParseVariableStatement(kStatement, NULL, ok);
|
| -
|
| - default:
|
| - return ParseExpressionOrLabelledStatement(labels, allow_function, ok);
|
| - }
|
| -}
|
| -
|
| -Statement* Parser::ParseStatementAsUnlabelled(
|
| - ZoneList<const AstRawString*>* labels, bool* ok) {
|
| - switch (peek()) {
|
| - case Token::CONTINUE:
|
| - return ParseContinueStatement(ok);
|
| -
|
| - case Token::BREAK:
|
| - return ParseBreakStatement(labels, ok);
|
| -
|
| - case Token::RETURN:
|
| - return ParseReturnStatement(ok);
|
| -
|
| - case Token::THROW:
|
| - return ParseThrowStatement(ok);
|
| -
|
| - case Token::TRY:
|
| - return ParseTryStatement(ok);
|
| -
|
| - default:
|
| - UNREACHABLE();
|
| - return NULL;
|
| - }
|
| -}
|
| -
|
| VariableProxy* Parser::NewUnresolved(const AstRawString* name, int begin_pos,
|
| int end_pos, Variable::Kind kind) {
|
| return scope()->NewUnresolved(factory(), name, begin_pos, end_pos, kind);
|
| @@ -1877,7 +1617,7 @@ Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
|
| {
|
| BlockState block_state(&scope_state_);
|
| block_state.set_start_position(scanner()->location().beg_pos);
|
| - Target target(&this->target_stack_, body);
|
| + ParserTarget target(this, body);
|
|
|
| while (peek() != Token::RBRACE) {
|
| Statement* stat = ParseStatementListItem(CHECK_OK);
|
| @@ -2349,7 +2089,7 @@ Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
|
| BlockState cases_block_state(&scope_state_);
|
| cases_block_state.set_start_position(scanner()->location().beg_pos);
|
| cases_block_state.SetNonlinear();
|
| - Target target(&this->target_stack_, switch_statement);
|
| + ParserTarget target(this, switch_statement);
|
|
|
| Expression* tag_read = factory()->NewVariableProxy(tag_variable);
|
|
|
| @@ -2455,7 +2195,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| {
|
| BlockState block_state(&scope_state_);
|
| block_state.set_start_position(scanner()->location().beg_pos);
|
| - Target target(&this->target_stack_, catch_block);
|
| + ParserTarget target(this, catch_block);
|
|
|
| const AstRawString* name = ast_value_factory()->dot_catch_string();
|
| Expression* pattern = nullptr;
|
| @@ -2594,7 +2334,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(
|
|
|
| DoWhileStatement* loop =
|
| factory()->NewDoWhileStatement(labels, peek_position());
|
| - Target target(&this->target_stack_, loop);
|
| + ParserTarget target(this, loop);
|
|
|
| Expect(Token::DO, CHECK_OK);
|
| Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
|
| @@ -2621,7 +2361,7 @@ WhileStatement* Parser::ParseWhileStatement(
|
| // 'while' '(' Expression ')' Statement
|
|
|
| WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
|
| - Target target(&this->target_stack_, loop);
|
| + ParserTarget target(this, loop);
|
|
|
| Expect(Token::WHILE, CHECK_OK);
|
| Expect(Token::LPAREN, CHECK_OK);
|
| @@ -3069,7 +2809,7 @@ Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels,
|
| bool legacy, bool* ok) {
|
| if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
|
| (legacy && allow_harmony_restrictive_declarations())) {
|
| - return ParseSubStatement(labels, kDisallowLabelledFunctionStatement, ok);
|
| + return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
|
| } else {
|
| if (legacy) {
|
| ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration];
|
| @@ -3178,7 +2918,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
|
| ForEachStatement* loop =
|
| factory()->NewForEachStatement(mode, labels, stmt_pos);
|
| - Target target(&this->target_stack_, loop);
|
| + ParserTarget target(this, loop);
|
|
|
| int each_keyword_position = scanner()->location().beg_pos;
|
|
|
| @@ -3324,7 +3064,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|
|
| ForEachStatement* loop =
|
| factory()->NewForEachStatement(mode, labels, stmt_pos);
|
| - Target target(&this->target_stack_, loop);
|
| + ParserTarget target(this, loop);
|
|
|
| int each_keyword_position = scanner()->location().beg_pos;
|
|
|
| @@ -3356,7 +3096,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|
|
| // Standard 'for' loop
|
| ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
|
| - Target target(&this->target_stack_, loop);
|
| + ParserTarget target(this, loop);
|
|
|
| // Parsed initializer at this point.
|
| Expect(Token::SEMICOLON, CHECK_OK);
|
| @@ -4815,7 +4555,7 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope,
|
| // Parser support
|
|
|
| bool Parser::TargetStackContainsLabel(const AstRawString* label) {
|
| - for (Target* t = target_stack_; t != NULL; t = t->previous()) {
|
| + for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
|
| if (ContainsLabel(t->statement()->labels(), label)) return true;
|
| }
|
| return false;
|
| @@ -4825,7 +4565,7 @@ bool Parser::TargetStackContainsLabel(const AstRawString* label) {
|
| BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
|
| bool* ok) {
|
| bool anonymous = label == NULL;
|
| - for (Target* t = target_stack_; t != NULL; t = t->previous()) {
|
| + for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
|
| BreakableStatement* stat = t->statement();
|
| if ((anonymous && stat->is_target_for_anonymous()) ||
|
| (!anonymous && ContainsLabel(stat->labels(), label))) {
|
| @@ -4839,7 +4579,7 @@ BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
|
| IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
|
| bool* ok) {
|
| bool anonymous = label == NULL;
|
| - for (Target* t = target_stack_; t != NULL; t = t->previous()) {
|
| + for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
|
| IterationStatement* stat = t->statement()->AsIterationStatement();
|
| if (stat == NULL) continue;
|
|
|
| @@ -5233,10 +4973,12 @@ void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
|
| scope->SetLanguageMode(mode);
|
| }
|
|
|
| -
|
| -void Parser::RaiseLanguageMode(LanguageMode mode) {
|
| - LanguageMode old = scope()->language_mode();
|
| - SetLanguageMode(scope(), old > mode ? old : mode);
|
| +void Parser::SetAsmModule() {
|
| + // Store the usage count; The actual use counter on the isolate is
|
| + // incremented after parsing is done.
|
| + ++use_counts_[v8::Isolate::kUseAsm];
|
| + DCHECK(scope()->is_declaration_scope());
|
| + scope()->AsDeclarationScope()->set_asm_module();
|
| }
|
|
|
| void Parser::MarkCollectedTailCallExpressions() {
|
|
|