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() { |