diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-10-18 15:03:02 -0700 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-10-18 17:01:41 -0700 |
commit | 3d1b3df9486c0e7708065257f7311902f6b7b366 (patch) | |
tree | cb051bdeaead11e06dcd97725783e0f113afb1bf /deps/v8/src/parsing/parser.cc | |
parent | e2cddbb8ccdb7b3c4a40c8acc630f68703bc77b5 (diff) | |
download | android-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.tar.gz android-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.tar.bz2 android-node-v8-3d1b3df9486c0e7708065257f7311902f6b7b366.zip |
deps: update V8 to 6.2.414.32
PR-URL: https://github.com/nodejs/node/pull/15362
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/parsing/parser.cc')
-rw-r--r-- | deps/v8/src/parsing/parser.cc | 895 |
1 files changed, 146 insertions, 749 deletions
diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 3da659ebed..9915a18881 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -19,10 +19,9 @@ #include "src/messages.h" #include "src/objects-inl.h" #include "src/parsing/duplicate-finder.h" -#include "src/parsing/parameter-initializer-rewriter.h" +#include "src/parsing/expression-scope-reparenter.h" #include "src/parsing/parse-info.h" #include "src/parsing/rewriter.h" -#include "src/parsing/scanner-character-streams.h" #include "src/runtime/runtime.h" #include "src/string-stream.h" #include "src/tracing/trace-event.h" @@ -478,7 +477,7 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name, Parser::Parser(ParseInfo* info) : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(), - info->extension(), info->ast_value_factory(), + info->extension(), info->GetOrCreateAstValueFactory(), info->runtime_call_stats(), true), scanner_(info->unicode_cache()), reusable_preparser_(nullptr), @@ -495,8 +494,7 @@ Parser::Parser(ParseInfo* info) // Even though we were passed ParseInfo, we should not store it in // Parser - this makes sure that Isolate is not accidentally accessed via // ParseInfo during background parsing. - DCHECK(!info->script().is_null() || info->source_stream() != nullptr || - info->character_stream() != nullptr); + DCHECK(info->character_stream() != nullptr); // Determine if functions can be lazily compiled. This is necessary to // allow some of our builtin JS files to be lazily compiled. These // builtins cannot be handled lazily by the parser, since we have to know @@ -529,14 +527,6 @@ Parser::Parser(ParseInfo* info) ++feature) { use_counts_[feature] = 0; } - if (info->ast_value_factory() == NULL) { - // info takes ownership of AstValueFactory. - info->set_ast_value_factory(new AstValueFactory( - zone(), info->ast_string_constants(), info->hash_seed())); - info->set_ast_value_factory_owned(); - ast_value_factory_ = info->ast_value_factory(); - ast_node_factory_.set_ast_value_factory(ast_value_factory_); - } } void Parser::DeserializeScopeChain( @@ -558,6 +548,19 @@ void Parser::DeserializeScopeChain( original_scope_ = scope; } +namespace { + +void MaybeResetCharacterStream(ParseInfo* info, FunctionLiteral* literal) { + // Don't reset the character stream if there is an asm.js module since it will + // be used again by the asm-parser. + if (!FLAG_stress_validate_asm && + (literal == nullptr || !literal->scope()->ContainsAsmModule())) { + info->ResetCharacterStream(); + } +} + +} // namespace + FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, // see comment for HistogramTimerScope class. @@ -569,8 +572,6 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { runtime_call_stats_, info->is_eval() ? &RuntimeCallStats::ParseEval : &RuntimeCallStats::ParseProgram); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram"); - Handle<String> source(String::cast(info->script()->source())); - isolate->counters()->total_parse_size()->Increment(source->length()); base::ElapsedTimer timer; if (FLAG_trace_parse) { timer.Start(); @@ -592,33 +593,12 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { DeserializeScopeChain(info, info->maybe_outer_scope_info()); - source = String::Flatten(source); - FunctionLiteral* result; + scanner_.Initialize(info->character_stream(), info->is_module()); + FunctionLiteral* result = DoParseProgram(info); + MaybeResetCharacterStream(info, result); - if (FLAG_use_parse_tasks) { - source_ = source; - compiler_dispatcher_ = isolate->compiler_dispatcher(); - main_parse_info_ = info; - } - - { - std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(source)); - scanner_.Initialize(stream.get(), info->is_module()); - result = DoParseProgram(info); - } - if (result != NULL) { - DCHECK_EQ(scanner_.peek_location().beg_pos, source->length()); - } HandleSourceURLComments(isolate, info->script()); - if (FLAG_use_parse_tasks) { - compiler_dispatcher_->FinishAllNow(); - StitchAst(info, isolate); - source_ = Handle<String>(); - compiler_dispatcher_ = nullptr; - main_parse_info_ = nullptr; - } - if (FLAG_trace_parse && result != nullptr) { double ms = timer.Elapsed().InMillisecondsF(); if (info->is_eval()) { @@ -749,20 +729,18 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { return result; } -FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info) { +FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, + Handle<SharedFunctionInfo> shared_info) { // It's OK to use the Isolate & counters here, since this function is only // called in the main thread. DCHECK(parsing_on_main_thread_); RuntimeCallTimerScope runtime_timer(runtime_call_stats_, &RuntimeCallStats::ParseFunction); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseFunction"); - Handle<String> source(String::cast(info->script()->source())); - isolate->counters()->total_parse_size()->Increment(source->length()); base::ElapsedTimer timer; if (FLAG_trace_parse) { timer.Start(); } - Handle<SharedFunctionInfo> shared_info = info->shared_info(); DeserializeScopeChain(info, info->maybe_outer_scope_info()); if (info->asm_function_scope()) { original_scope_ = info->asm_function_scope(); @@ -772,19 +750,15 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info) { } // Initialize parser state. - source = String::Flatten(source); - FunctionLiteral* result; - { - std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For( - source, shared_info->start_position(), shared_info->end_position())); - Handle<String> name(shared_info->name()); - scanner_.Initialize(stream.get(), info->is_module()); - info->set_function_name(ast_value_factory()->GetString(name)); - result = DoParseFunction(info); - if (result != nullptr) { - Handle<String> inferred_name(shared_info->inferred_name()); - result->set_inferred_name(inferred_name); - } + Handle<String> name(shared_info->name()); + info->set_function_name(ast_value_factory()->GetString(name)); + scanner_.Initialize(info->character_stream(), info->is_module()); + + FunctionLiteral* result = DoParseFunction(info, info->function_name()); + MaybeResetCharacterStream(info, result); + if (result != nullptr) { + Handle<String> inferred_name(shared_info->inferred_name()); + result->set_inferred_name(inferred_name); } if (FLAG_trace_parse && result != NULL) { @@ -809,25 +783,8 @@ static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) { return FunctionLiteral::kAnonymousExpression; } -FunctionLiteral* Parser::DoParseFunction(ParseInfo* info) { - const AstRawString* raw_name = info->function_name(); - FunctionNameValidity function_name_validity = kSkipFunctionNameCheck; - if (!raw_name) { - bool ok = true; - if (peek() == Token::LPAREN) { - const AstRawString* variable_name; - impl()->GetDefaultStrings(&raw_name, &variable_name); - } else { - bool is_strict_reserved = true; - raw_name = ParseIdentifierOrStrictReservedWord(info->function_kind(), - &is_strict_reserved, &ok); - if (!ok) return nullptr; - function_name_validity = is_strict_reserved - ? kFunctionNameIsStrictReserved - : kFunctionNameValidityUnknown; - } - } - +FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, + const AstRawString* raw_name) { DCHECK_NOT_NULL(raw_name); DCHECK_NULL(scope_); DCHECK_NULL(target_stack_); @@ -949,7 +906,7 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info) { info->start_position(), info->end_position()); } else { result = ParseFunctionLiteral( - raw_name, Scanner::Location::invalid(), function_name_validity, kind, + raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind, kNoSourcePosition, function_type, info->language_mode(), &ok); } // Make sure the results agree. @@ -1432,8 +1389,13 @@ Declaration* Parser::DeclareVariable(const AstRawString* name, DCHECK_NOT_NULL(name); VariableProxy* proxy = factory()->NewVariableProxy( name, NORMAL_VARIABLE, scanner()->location().beg_pos); - Declaration* declaration = - factory()->NewVariableDeclaration(proxy, this->scope(), pos); + Declaration* declaration; + if (mode == VAR && !scope()->is_declaration_scope()) { + DCHECK(scope()->is_block_scope() || scope()->is_with_scope()); + declaration = factory()->NewNestedVariableDeclaration(proxy, scope(), pos); + } else { + declaration = factory()->NewVariableDeclaration(proxy, pos); + } Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, ok, nullptr, scanner()->location().end_pos); if (!*ok) return nullptr; @@ -1459,11 +1421,11 @@ Variable* Parser::Declare(Declaration* declaration, var_end_pos != kNoSourcePosition ? var_end_pos : declaration->proxy()->position() + 1); - if (declaration_kind == DeclarationDescriptor::NORMAL) { + if (declaration_kind == DeclarationDescriptor::PARAMETER) { + ReportMessageAt(loc, MessageTemplate::kParamDupe); + } else { ReportMessageAt(loc, MessageTemplate::kVarRedeclaration, declaration->proxy()->raw_name()); - } else { - ReportMessageAt(loc, MessageTemplate::kParamDupe); } return nullptr; } @@ -1476,25 +1438,14 @@ Variable* Parser::Declare(Declaration* declaration, Block* Parser::BuildInitializationBlock( DeclarationParsingResult* parsing_result, ZoneList<const AstRawString*>* names, bool* ok) { - Block* result = factory()->NewBlock( - NULL, 1, true, parsing_result->descriptor.declaration_pos); + Block* result = factory()->NewBlock(1, true); for (auto declaration : parsing_result->declarations) { - PatternRewriter::DeclareAndInitializeVariables( - this, result, &(parsing_result->descriptor), &declaration, names, - CHECK_OK); + DeclareAndInitializeVariables(result, &(parsing_result->descriptor), + &declaration, names, CHECK_OK); } return result; } -void Parser::DeclareAndInitializeVariables( - Block* block, const DeclarationDescriptor* declaration_descriptor, - const DeclarationParsingResult::Declaration* declaration, - ZoneList<const AstRawString*>* names, bool* ok) { - DCHECK_NOT_NULL(block); - PatternRewriter::DeclareAndInitializeVariables( - this, block, declaration_descriptor, declaration, names, ok); -} - Statement* Parser::DeclareFunction(const AstRawString* variable_name, FunctionLiteral* function, VariableMode mode, int pos, bool is_sloppy_block_function, @@ -1504,7 +1455,7 @@ Statement* Parser::DeclareFunction(const AstRawString* variable_name, factory()->NewVariableProxy(variable_name, NORMAL_VARIABLE); Declaration* declaration = - factory()->NewFunctionDeclaration(proxy, function, scope(), pos); + factory()->NewFunctionDeclaration(proxy, function, pos); Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized, CHECK_OK); if (names) names->Add(variable_name, zone()); @@ -1589,7 +1540,7 @@ bool Parser::ContainsLabel(ZoneList<const AstRawString*>* labels, } Block* Parser::IgnoreCompletion(Statement* statement) { - Block* block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); + Block* block = factory()->NewBlock(1, true); block->statements()->Add(statement, zone()); return block; } @@ -1647,7 +1598,7 @@ Statement* Parser::RewriteSwitchStatement(Expression* tag, // } // } - Block* switch_block = factory()->NewBlock(NULL, 2, false, kNoSourcePosition); + Block* switch_block = factory()->NewBlock(2, false); Variable* tag_variable = NewTemporary(ast_value_factory()->dot_switch_tag_string()); @@ -1668,7 +1619,7 @@ Statement* Parser::RewriteSwitchStatement(Expression* tag, Expression* tag_read = factory()->NewVariableProxy(tag_variable); switch_statement->Initialize(tag_read, cases); - Block* cases_block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); + Block* cases_block = factory()->NewBlock(1, false); cases_block->statements()->Add(switch_statement, zone()); cases_block->set_scope(scope); DCHECK_IMPLIES(scope != nullptr, @@ -1701,11 +1652,9 @@ void Parser::RewriteCatchPattern(CatchInfo* catch_info, bool* ok) { catch_info->pattern, initializer_position, factory()->NewVariableProxy(catch_variable)); - catch_info->init_block = - factory()->NewBlock(nullptr, 8, true, kNoSourcePosition); - PatternRewriter::DeclareAndInitializeVariables( - this, catch_info->init_block, &descriptor, &decl, - &catch_info->bound_names, ok); + catch_info->init_block = factory()->NewBlock(8, true); + DeclareAndInitializeVariables(catch_info->init_block, &descriptor, &decl, + &catch_info->bound_names, ok); } else { catch_info->bound_names.Add(catch_info->name, zone()); } @@ -1748,7 +1697,7 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block, catch_block, kNoSourcePosition); RecordTryCatchStatementSourceRange(statement, catch_range); - try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); + try_block = factory()->NewBlock(1, false); try_block->statements()->Add(statement, zone()); catch_block = nullptr; // Clear to indicate it's been handled. } @@ -1803,7 +1752,7 @@ void Parser::ParseAndRewriteAsyncGeneratorFunctionBody( // "done" iterator result object containing a Promise-unwrapped value. DCHECK(IsAsyncGeneratorFunction(kind)); - Block* try_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); + Block* try_block = factory()->NewBlock(3, false); Expression* initial_yield = BuildInitialYield(pos, kind); try_block->statements()->Add( factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), @@ -1818,7 +1767,7 @@ void Parser::ParseAndRewriteAsyncGeneratorFunctionBody( try_block->statements()->Add(final_return, zone()); // For AsyncGenerators, a top-level catch block will reject the Promise. - Scope* catch_scope = NewHiddenCatchScopeWithParent(scope()); + Scope* catch_scope = NewHiddenCatchScope(); ZoneList<Expression*>* reject_args = new (zone()) ZoneList<Expression*>(2, zone()); @@ -1836,11 +1785,10 @@ void Parser::ParseAndRewriteAsyncGeneratorFunctionBody( TryStatement* try_catch = factory()->NewTryCatchStatementForAsyncAwait( try_block, catch_scope, catch_block, kNoSourcePosition); - try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); + try_block = factory()->NewBlock(1, false); try_block->statements()->Add(try_catch, zone()); - Block* finally_block = - factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); + Block* finally_block = factory()->NewBlock(1, false); ZoneList<Expression*>* close_args = new (zone()) ZoneList<Expression*>(1, zone()); VariableProxy* call_proxy = factory()->NewVariableProxy( @@ -1937,11 +1885,10 @@ Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt, if (each->IsArrayLiteral() || each->IsObjectLiteral()) { Variable* temp = NewTemporary(ast_value_factory()->empty_string()); VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); - Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( - this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, - kNoSourcePosition), - scope()); - auto block = factory()->NewBlock(nullptr, 2, false, kNoSourcePosition); + Expression* assign_each = + RewriteDestructuringAssignment(factory()->NewAssignment( + Token::ASSIGN, each, temp_proxy, kNoSourcePosition)); + auto block = factory()->NewBlock(2, false); block->statements()->Add( factory()->NewExpressionStatement(assign_each, kNoSourcePosition), zone()); @@ -1979,8 +1926,7 @@ Block* Parser::RewriteForVarInLegacy(const ForInfo& for_info) { ++use_counts_[v8::Isolate::kForInInitializer]; const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name(); VariableProxy* single_var = NewUnresolved(name); - Block* init_block = factory()->NewBlock( - nullptr, 2, true, for_info.parsing_result.descriptor.declaration_pos); + Block* init_block = factory()->NewBlock(2, true); init_block->statements()->Add( factory()->NewExpressionStatement( factory()->NewAssignment(Token::ASSIGN, single_var, @@ -2014,14 +1960,12 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info, DeclarationParsingResult::Declaration& decl = for_info->parsing_result.declarations[0]; Variable* temp = NewTemporary(ast_value_factory()->dot_for_string()); - auto each_initialization_block = - factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); + auto each_initialization_block = factory()->NewBlock(1, true); { auto descriptor = for_info->parsing_result.descriptor; descriptor.declaration_pos = kNoSourcePosition; descriptor.initialization_pos = kNoSourcePosition; descriptor.scope = scope(); - descriptor.declaration_kind = DeclarationDescriptor::LEXICAL_FOR_EACH; decl.initializer = factory()->NewVariableProxy(temp); bool is_for_var_of = @@ -2031,8 +1975,8 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info, IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) || is_for_var_of; - PatternRewriter::DeclareAndInitializeVariables( - this, each_initialization_block, &descriptor, &decl, + DeclareAndInitializeVariables( + each_initialization_block, &descriptor, &decl, collect_names ? &for_info->bound_names : nullptr, CHECK_OK_VOID); // Annex B.3.5 prohibits the form @@ -2061,7 +2005,7 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info, } } - *body_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); + *body_block = factory()->NewBlock(3, false); (*body_block)->statements()->Add(each_initialization_block, zone()); *each_variable = factory()->NewVariableProxy(temp, for_info->position); } @@ -2072,7 +2016,7 @@ Block* Parser::CreateForEachStatementTDZ(Block* init_block, if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) { DCHECK_NULL(init_block); - init_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); + init_block = factory()->NewBlock(1, false); for (int i = 0; i < for_info.bound_names.length(); ++i) { // TODO(adamk): This needs to be some sort of special @@ -2143,32 +2087,21 @@ Statement* Parser::InitializeForOfStatement( result_value = factory()->NewProperty(result_proxy, value_literal, nopos); } - // {{completion = kAbruptCompletion;}} - Statement* set_completion_abrupt; - if (finalize) { - Expression* proxy = factory()->NewVariableProxy(completion); - Expression* assignment = factory()->NewAssignment( - Token::ASSIGN, proxy, - factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos); - - set_completion_abrupt = - IgnoreCompletion(factory()->NewExpressionStatement(assignment, nopos)); - } - - // do { let tmp = #result_value; #set_completion_abrupt; tmp } + // {{tmp = #result_value, completion = kAbruptCompletion, tmp}} // Expression* result_value (gets overwritten) if (finalize) { - Variable* var_tmp = NewTemporary(avfactory->empty_string()); - Expression* tmp = factory()->NewVariableProxy(var_tmp); - Expression* assignment = - factory()->NewAssignment(Token::ASSIGN, tmp, result_value, nopos); + Variable* tmp = NewTemporary(avfactory->empty_string()); + Expression* save_result = factory()->NewAssignment( + Token::ASSIGN, factory()->NewVariableProxy(tmp), result_value, nopos); - Block* block = factory()->NewBlock(nullptr, 2, false, nopos); - block->statements()->Add( - factory()->NewExpressionStatement(assignment, nopos), zone()); - block->statements()->Add(set_completion_abrupt, zone()); + Expression* set_completion_abrupt = factory()->NewAssignment( + Token::ASSIGN, factory()->NewVariableProxy(completion), + factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos); - result_value = factory()->NewDoExpression(block, var_tmp, nopos); + result_value = factory()->NewBinaryOperation(Token::COMMA, save_result, + set_completion_abrupt, nopos); + result_value = factory()->NewBinaryOperation( + Token::COMMA, result_value, factory()->NewVariableProxy(tmp), nopos); } // each = #result_value; @@ -2177,8 +2110,7 @@ Statement* Parser::InitializeForOfStatement( assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, nopos); if (each->IsArrayLiteral() || each->IsObjectLiteral()) { - assign_each = PatternRewriter::RewriteDestructuringAssignment( - this, assign_each->AsAssignment(), scope()); + assign_each = RewriteDestructuringAssignment(assign_each->AsAssignment()); } } @@ -2197,7 +2129,7 @@ Statement* Parser::InitializeForOfStatement( // { #loop-body; #set_completion_normal } // Statement* body (gets overwritten) if (finalize) { - Block* block = factory()->NewBlock(nullptr, 2, false, nopos); + Block* block = factory()->NewBlock(2, false); block->statements()->Add(body, zone()); block->statements()->Add(set_completion_normal, zone()); body = block; @@ -2211,8 +2143,7 @@ Statement* Parser::InitializeForOfStatement( Statement* Parser::DesugarLexicalBindingsInForStatement( ForStatement* loop, Statement* init, Expression* cond, Statement* next, - Statement* body, const SourceRange& body_range, Scope* inner_scope, - const ForInfo& for_info, bool* ok) { + Statement* body, Scope* inner_scope, const ForInfo& for_info, bool* ok) { // ES6 13.7.4.8 specifies that on each loop iteration the let variables are // copied into a new environment. Moreover, the "next" statement must be // evaluated not in the environment of the just completed iteration but in @@ -2253,8 +2184,8 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( DCHECK(for_info.bound_names.length() > 0); ZoneList<Variable*> temps(for_info.bound_names.length(), zone()); - Block* outer_block = factory()->NewBlock( - nullptr, for_info.bound_names.length() + 4, false, kNoSourcePosition); + Block* outer_block = + factory()->NewBlock(for_info.bound_names.length() + 4, false); // Add statement: let/const x = i. outer_block->statements()->Add(init, zone()); @@ -2304,12 +2235,12 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( outer_block->statements()->Add(outer_loop, zone()); outer_block->set_scope(scope()); - Block* inner_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition); + Block* inner_block = factory()->NewBlock(3, false); { BlockState block_state(&scope_, inner_scope); - Block* ignore_completion_block = factory()->NewBlock( - nullptr, for_info.bound_names.length() + 3, true, kNoSourcePosition); + Block* ignore_completion_block = + factory()->NewBlock(for_info.bound_names.length() + 3, true); ZoneList<Variable*> inner_vars(for_info.bound_names.length(), zone()); // For each let variable x: // make statement: let/const x = temp_x. @@ -2323,8 +2254,9 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( Token::INIT, decl->proxy(), temp_proxy, kNoSourcePosition); Statement* assignment_statement = factory()->NewExpressionStatement(assignment, kNoSourcePosition); - DCHECK(init->position() != kNoSourcePosition); - decl->proxy()->var()->set_initializer_position(init->position()); + int declaration_pos = for_info.parsing_result.descriptor.declaration_pos; + DCHECK(declaration_pos != kNoSourcePosition); + decl->proxy()->var()->set_initializer_position(declaration_pos); ignore_completion_block->statements()->Add(assignment_statement, zone()); } @@ -2443,7 +2375,6 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( } outer_loop->Initialize(NULL, NULL, NULL, inner_block); - RecordIterationStatementSourceRange(outer_loop, body_range); return outer_block; } @@ -2492,8 +2423,13 @@ void Parser::AddArrowFunctionFormalParameters( Expression* initializer = nullptr; if (expr->IsAssignment()) { + if (expr->IsRewritableExpression()) { + // This expression was parsed as a possible destructuring assignment. + // Mark it as already-rewritten to avoid an unnecessary visit later. + expr->AsRewritableExpression()->set_rewritten(); + } Assignment* assignment = expr->AsAssignment(); - DCHECK(!assignment->is_compound()); + DCHECK(!assignment->IsCompoundAssignment()); initializer = assignment->value(); expr = assignment->target(); } @@ -2607,16 +2543,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral( DCHECK_IMPLIES(parse_lazily(), allow_lazy_); DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr); - const bool source_is_external = - !source_.is_null() && (source_->IsExternalTwoByteString() || - source_->IsExternalOneByteString()); const bool is_lazy = eager_compile_hint == FunctionLiteral::kShouldLazyCompile; const bool is_top_level = impl()->AllowsLazyParsingWithoutUnresolvedVariables(); const bool is_lazy_top_level_function = is_lazy && is_top_level; const bool is_lazy_inner_function = is_lazy && !is_top_level; - const bool is_eager_top_level_function = !is_lazy && is_top_level; const bool is_expression = function_type == FunctionLiteral::kAnonymousExpression || function_type == FunctionLiteral::kNamedExpression; @@ -2648,51 +2580,18 @@ FunctionLiteral* Parser::ParseFunctionLiteral( parse_lazily() && FLAG_lazy_inner_functions && is_lazy_inner_function && (!is_expression || FLAG_aggressive_lazy_inner_functions); - bool should_use_parse_task = - FLAG_use_parse_tasks && parse_lazily() && compiler_dispatcher_ && - is_eager_top_level_function && source_is_external; - // This may be modified later to reflect preparsing decision taken - bool should_preparse = (parse_lazily() && (is_lazy_top_level_function || - should_use_parse_task)) || - should_preparse_inner; + bool should_preparse = + (parse_lazily() && is_lazy_top_level_function) || should_preparse_inner; ZoneList<Statement*>* body = nullptr; int expected_property_count = -1; - bool should_be_used_once_hint = false; int num_parameters = -1; int function_length = -1; bool has_duplicate_parameters = false; int function_literal_id = GetNextFunctionLiteralId(); ProducedPreParsedScopeData* produced_preparsed_scope_data = nullptr; - Expect(Token::LPAREN, CHECK_OK); - - if (should_use_parse_task) { - int start_pos = scanner()->location().beg_pos; - if (function_name_location.IsValid()) { - start_pos = function_name_location.beg_pos; - } - // Warning! - // Only sets fields in compiler_hints that are currently used. - int compiler_hints = SharedFunctionInfo::FunctionKindBits::encode(kind); - if (function_type == FunctionLiteral::kDeclaration) { - compiler_hints |= SharedFunctionInfo::IsDeclarationBit::encode(true); - } - should_use_parse_task = compiler_dispatcher_->Enqueue( - source_, start_pos, source_->length(), language_mode, - function_literal_id, allow_natives(), parsing_module_, - function_type == FunctionLiteral::kNamedExpression, compiler_hints, - main_parse_info_, nullptr); - if (V8_UNLIKELY(FLAG_trace_parse_tasks)) { - PrintF("Spining off task for function at %d: %s\n", start_pos, - should_use_parse_task ? "SUCCESS" : "FAILED"); - } - if (!should_use_parse_task) { - should_preparse = false; - } - } - Zone* outer_zone = zone(); DeclarationScope* scope; @@ -2717,6 +2616,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( scope->SetScopeName(function_name); if (should_preparse) scope->set_needs_migration(); #endif + + Expect(Token::LPAREN, CHECK_OK); scope->set_start_position(scanner()->location().beg_pos); // Eager or lazy parse? If is_lazy_top_level_function, we'll parse @@ -2726,8 +2627,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // try to lazy parse in the first place, we'll have to parse eagerly. if (should_preparse) { DCHECK(parse_lazily()); - DCHECK(is_lazy_top_level_function || is_lazy_inner_function || - should_use_parse_task); + DCHECK(is_lazy_top_level_function || is_lazy_inner_function); Scanner::BookmarkScope bookmark(scanner()); bookmark.Set(); LazyParsingResult result = SkipFunction( @@ -2739,15 +2639,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral( DCHECK(is_lazy_top_level_function); bookmark.Apply(); // This is probably an initialization function. Inform the compiler it - // should also eager-compile this function, and that we expect it to be - // used once. + // should also eager-compile this function. eager_compile_hint = FunctionLiteral::kShouldEagerCompile; - should_be_used_once_hint = true; scope->ResetAfterPreparsing(ast_value_factory(), true); zone_scope.Reset(); // Trigger eager (re-)parsing, just below this block. should_preparse = false; - should_use_parse_task = false; } } @@ -2808,12 +2705,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( function_name, scope, body, expected_property_count, num_parameters, function_length, duplicate_parameters, function_type, eager_compile_hint, pos, true, function_literal_id, produced_preparsed_scope_data); - if (should_use_parse_task) { - literals_to_stitch_.emplace_back(function_literal); - } function_literal->set_function_token_position(function_token_pos); - if (should_be_used_once_hint) - function_literal->set_should_be_used_once_hint(); if (should_infer_name) { DCHECK_NOT_NULL(fni_); @@ -2866,7 +2758,7 @@ Parser::LazyParsingResult Parser::SkipFunction( // FIXME(marja): There are 3 ways to skip functions now. Unify them. DCHECK_NOT_NULL(consumed_preparsed_scope_data_); if (consumed_preparsed_scope_data_->HasData()) { - DCHECK(FLAG_experimental_preparser_scope_analysis); + DCHECK(FLAG_preparser_scope_analysis); int end_position; LanguageMode language_mode; int num_inner_functions; @@ -2969,11 +2861,8 @@ Statement* Parser::BuildAssertIsCoercible(Variable* var, class InitializerRewriter final : public AstTraversalVisitor<InitializerRewriter> { public: - InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser, - Scope* scope) - : AstTraversalVisitor(stack_limit, root), - parser_(parser), - scope_(scope) {} + InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser) + : AstTraversalVisitor(stack_limit, root), parser_(parser) {} private: // This is required so that the overriden Visit* methods can be @@ -2983,8 +2872,7 @@ class InitializerRewriter final // Just rewrite destructuring assignments wrapped in RewritableExpressions. void VisitRewritableExpression(RewritableExpression* to_rewrite) { if (to_rewrite->is_rewritten()) return; - Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite, - scope_); + parser_->RewriteDestructuringAssignment(to_rewrite); AstTraversalVisitor::VisitRewritableExpression(to_rewrite); } @@ -2993,12 +2881,10 @@ class InitializerRewriter final void VisitFunctionLiteral(FunctionLiteral* expr) {} Parser* parser_; - Scope* scope_; }; - -void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) { - InitializerRewriter rewriter(stack_limit_, expr, this, scope); +void Parser::RewriteParameterInitializer(Expression* expr) { + InitializerRewriter rewriter(stack_limit_, expr, this); rewriter.Run(); } @@ -3008,7 +2894,7 @@ Block* Parser::BuildParameterInitializationBlock( DCHECK(!parameters.is_simple); DCHECK(scope()->is_function_scope()); DCHECK_EQ(scope(), parameters.scope); - Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition); + Block* init_block = factory()->NewBlock(1, true); int index = 0; for (auto parameter : parameters.params) { DeclarationDescriptor descriptor; @@ -3028,7 +2914,7 @@ Block* Parser::BuildParameterInitializationBlock( // IS_UNDEFINED($param) ? initializer : $param // Ensure initializer is rewritten - RewriteParameterInitializer(parameter->initializer, scope()); + RewriteParameterInitializer(parameter->initializer); auto condition = factory()->NewCompareOperation( Token::EQ_STRICT, @@ -3041,12 +2927,13 @@ Block* Parser::BuildParameterInitializationBlock( Scope* param_scope = scope(); Block* param_block = init_block; - if (!parameter->is_simple() && scope()->calls_sloppy_eval()) { + if (!parameter->is_simple() && + scope()->AsDeclarationScope()->calls_sloppy_eval()) { param_scope = NewVarblockScope(); param_scope->set_start_position(descriptor.initialization_pos); param_scope->set_end_position(parameter->initializer_end_position); param_scope->RecordEvalCall(); - param_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); + param_block = factory()->NewBlock(8, true); param_block->set_scope(param_scope); // Pass the appropriate scope in so that PatternRewriter can appropriately // rewrite inner initializers of the pattern to param_scope @@ -3058,8 +2945,8 @@ Block* Parser::BuildParameterInitializationBlock( BlockState block_state(&scope_, param_scope); DeclarationParsingResult::Declaration decl( parameter->pattern, parameter->initializer_end_position, initial_value); - PatternRewriter::DeclareAndInitializeVariables( - this, param_block, &descriptor, &decl, nullptr, CHECK_OK); + DeclareAndInitializeVariables(param_block, &descriptor, &decl, nullptr, + CHECK_OK); if (param_block != init_block) { param_scope = param_scope->FinalizeBlockScope(); @@ -3073,8 +2960,8 @@ Block* Parser::BuildParameterInitializationBlock( return init_block; } -Scope* Parser::NewHiddenCatchScopeWithParent(Scope* parent) { - Scope* catch_scope = NewScopeWithParent(parent, CATCH_SCOPE); +Scope* Parser::NewHiddenCatchScope() { + Scope* catch_scope = NewScopeWithParent(scope(), CATCH_SCOPE); catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR); catch_scope->set_is_hidden(); return catch_scope; @@ -3090,7 +2977,7 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block) { // } finally { // %AsyncFunctionPromiseRelease(.promise); // } - Block* result = factory()->NewBlock(nullptr, 2, true, kNoSourcePosition); + Block* result = factory()->NewBlock(2, true); // .promise = %AsyncFunctionPromiseCreate(); Statement* set_promise; @@ -3107,7 +2994,7 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block) { result->statements()->Add(set_promise, zone()); // catch (.catch) { return %RejectPromise(.promise, .catch), .promise } - Scope* catch_scope = NewHiddenCatchScopeWithParent(scope()); + Scope* catch_scope = NewHiddenCatchScope(); Expression* promise_reject = BuildRejectPromise( factory()->NewVariableProxy(catch_scope->catch_variable()), @@ -3202,8 +3089,6 @@ ZoneList<Statement*>* Parser::ParseFunction( DuplicateFinder duplicate_finder; ExpressionClassifier formals_classifier(this, &duplicate_finder); - if (IsResumableFunction(kind)) PrepareGeneratorVariables(); - int expected_parameters_end_pos = parameters_end_pos_; if (expected_parameters_end_pos != kNoSourcePosition) { // This is the first function encountered in a CreateDynamicFunction eval. @@ -3271,8 +3156,8 @@ void Parser::DeclareClassVariable(const AstRawString* name, if (name != nullptr) { class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); - Declaration* declaration = factory()->NewVariableDeclaration( - class_info->proxy, scope(), class_token_pos); + Declaration* declaration = + factory()->NewVariableDeclaration(class_info->proxy, class_token_pos); Declare(declaration, DeclarationDescriptor::NORMAL, CONST, Variable::DefaultInitializationFlag(CONST), ok); } @@ -3289,7 +3174,7 @@ void Parser::DeclareClassProperty(const AstRawString* class_name, ClassInfo* class_info, bool* ok) { if (is_constructor) { DCHECK(!class_info->constructor); - class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral(); + class_info->constructor = property->value()->AsFunctionLiteral(); DCHECK_NOT_NULL(class_info->constructor); class_info->constructor->set_raw_name( class_name != nullptr ? ast_value_factory()->NewConsString(class_name) @@ -3496,19 +3381,7 @@ void Parser::ParseOnBackground(ParseInfo* info) { } } - std::unique_ptr<Utf16CharacterStream> stream; - Utf16CharacterStream* stream_ptr; - if (info->character_stream()) { - DCHECK(info->source_stream() == nullptr); - stream_ptr = info->character_stream(); - } else { - DCHECK(info->character_stream() == nullptr); - stream.reset(ScannerStream::For(info->source_stream(), - info->source_stream_encoding(), - runtime_call_stats_)); - stream_ptr = stream.get(); - } - scanner_.Initialize(stream_ptr, info->is_module()); + scanner_.Initialize(info->character_stream(), info->is_module()); DCHECK(info->maybe_outer_scope_info().is_null()); DCHECK(original_scope_); @@ -3523,8 +3396,9 @@ void Parser::ParseOnBackground(ParseInfo* info) { fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); result = DoParseProgram(info); } else { - result = DoParseFunction(info); + result = DoParseFunction(info, info->function_name()); } + MaybeResetCharacterStream(info, result); info->set_literal(result); @@ -3828,17 +3702,6 @@ Expression* Parser::ExpressionListToExpression(ZoneList<Expression*>* args) { return expr; } -// This method intoduces the line initializing the generator object -// when desugaring the body of async_function. -void Parser::PrepareAsyncFunctionBody(ZoneList<Statement*>* body, - FunctionKind kind, int pos) { - // When parsing an async arrow function, we get here without having called - // PrepareGeneratorVariables yet, so do it now. - if (function_state_->scope()->generator_object_var() == nullptr) { - PrepareGeneratorVariables(); - } -} - // This method completes the desugaring of the body of async_function. void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block, Expression* return_value, bool* ok) { @@ -3926,7 +3789,8 @@ void Parser::RewriteDestructuringAssignments() { // pair.scope may already have been removed by FinalizeBlockScope in the // meantime. Scope* scope = pair.scope->GetUnremovedScope(); - PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); + BlockState block_state(&scope_, scope); + RewriteDestructuringAssignment(to_rewrite); } } } @@ -4004,7 +3868,7 @@ Expression* Parser::RewriteSpreads(ArrayLiteral* lit) { // $R = lit Expression* init_result = factory()->NewAssignment( Token::INIT, factory()->NewVariableProxy(result), lit, kNoSourcePosition); - Block* do_block = factory()->NewBlock(nullptr, 16, false, kNoSourcePosition); + Block* do_block = factory()->NewBlock(16, false); do_block->statements()->Add( factory()->NewExpressionStatement(init_result, kNoSourcePosition), zone()); @@ -4151,430 +4015,6 @@ void Parser::SetFunctionName(Expression* value, const AstRawString* name, } } -// Desugaring of yield* -// ==================== -// -// With the help of do-expressions and function.sent, we desugar yield* into a -// loop containing a "raw" yield (a yield that doesn't wrap an iterator result -// object around its argument). Concretely, "yield* iterable" turns into -// roughly the following code: -// -// do { -// const kNext = 0; -// const kReturn = 1; -// const kThrow = 2; -// -// let input = undefined; -// let mode = kNext; -// let output = undefined; -// -// let iterator = GetIterator(iterable); -// -// while (true) { -// // From the generator to the iterator: -// // Forward input according to resume mode and obtain output. -// switch (mode) { -// case kNext: -// output = iterator.next(input); -// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); -// break; -// case kReturn: -// IteratorClose(iterator, input, output); // See below. -// break; -// case kThrow: -// let iteratorThrow = iterator.throw; -// if (IS_NULL_OR_UNDEFINED(iteratorThrow)) { -// IteratorClose(iterator); // See below. -// throw MakeTypeError(kThrowMethodMissing); -// } -// output = %_Call(iteratorThrow, iterator, input); -// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); -// break; -// } -// if (output.done) break; -// -// // From the generator to its user: -// // Forward output, receive new input, and determine resume mode. -// RawYield(output); // See explanation above. -// mode = %GeneratorGetResumeMode(); -// input = function.sent; -// } -// } -// -// if (mode === kReturn) { -// return {value: output.value, done: true}; -// } -// output.value -// } -// -// IteratorClose(iterator) expands to the following: -// -// let iteratorReturn = iterator.return; -// if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { -// let output = %_Call(iteratorReturn, iterator); -// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); -// } -// -// IteratorClose(iterator, input, output) expands to the following: -// -// let iteratorReturn = iterator.return; -// if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input; -// output = %_Call(iteratorReturn, iterator, input); -// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); - -Expression* Parser::RewriteYieldStar(Expression* iterable, int pos) { - const int nopos = kNoSourcePosition; - IteratorType type = - is_async_generator() ? IteratorType::kAsync : IteratorType::kNormal; - - if (type == IteratorType::kNormal) { - return factory()->NewYieldStar(iterable, pos); - } - - // Forward definition for break/continue statements. - WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos); - - // let input = undefined; - Variable* var_input = NewTemporary(ast_value_factory()->empty_string()); - Statement* initialize_input; - { - Expression* input_proxy = factory()->NewVariableProxy(var_input); - Expression* assignment = - factory()->NewAssignment(Token::ASSIGN, input_proxy, - factory()->NewUndefinedLiteral(nopos), nopos); - initialize_input = factory()->NewExpressionStatement(assignment, nopos); - } - - // let mode = kNext; - Variable* var_mode = NewTemporary(ast_value_factory()->empty_string()); - Statement* initialize_mode; - { - Expression* mode_proxy = factory()->NewVariableProxy(var_mode); - Expression* knext = - factory()->NewSmiLiteral(JSGeneratorObject::kNext, nopos); - Expression* assignment = - factory()->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos); - initialize_mode = factory()->NewExpressionStatement(assignment, nopos); - } - - // let output = undefined; - Variable* var_output = NewTemporary(ast_value_factory()->empty_string()); - Statement* initialize_output; - { - Expression* output_proxy = factory()->NewVariableProxy(var_output); - Expression* assignment = - factory()->NewAssignment(Token::ASSIGN, output_proxy, - factory()->NewUndefinedLiteral(nopos), nopos); - initialize_output = factory()->NewExpressionStatement(assignment, nopos); - } - - // let iterator = GetIterator(iterable); - Variable* var_iterator = NewTemporary(ast_value_factory()->empty_string()); - Statement* get_iterator; - { - Expression* iterator = factory()->NewGetIterator(iterable, type, nopos); - Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator); - Expression* assignment = factory()->NewAssignment( - Token::ASSIGN, iterator_proxy, iterator, nopos); - get_iterator = factory()->NewExpressionStatement(assignment, nopos); - } - - // output = iterator.next(input); - Statement* call_next; - { - Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator); - Expression* literal = - factory()->NewStringLiteral(ast_value_factory()->next_string(), nopos); - Expression* next_property = - factory()->NewProperty(iterator_proxy, literal, nopos); - Expression* input_proxy = factory()->NewVariableProxy(var_input); - auto args = new (zone()) ZoneList<Expression*>(1, zone()); - args->Add(input_proxy, zone()); - Expression* call = factory()->NewCall(next_property, args, nopos); - if (type == IteratorType::kAsync) { - call = factory()->NewAwait(call, nopos); - } - Expression* output_proxy = factory()->NewVariableProxy(var_output); - Expression* assignment = - factory()->NewAssignment(Token::ASSIGN, output_proxy, call, nopos); - call_next = factory()->NewExpressionStatement(assignment, nopos); - } - - // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); - Statement* validate_next_output; - { - Expression* is_receiver_call; - { - auto args = new (zone()) ZoneList<Expression*>(1, zone()); - args->Add(factory()->NewVariableProxy(var_output), zone()); - is_receiver_call = - factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); - } - - Statement* throw_call; - { - auto args = new (zone()) ZoneList<Expression*>(1, zone()); - args->Add(factory()->NewVariableProxy(var_output), zone()); - Expression* call = factory()->NewCallRuntime( - Runtime::kThrowIteratorResultNotAnObject, args, nopos); - throw_call = factory()->NewExpressionStatement(call, nopos); - } - - validate_next_output = factory()->NewIfStatement( - is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call, - nopos); - } - - // let iteratorThrow = iterator.throw; - Variable* var_throw = NewTemporary(ast_value_factory()->empty_string()); - Statement* get_throw; - { - Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator); - Expression* literal = - factory()->NewStringLiteral(ast_value_factory()->throw_string(), nopos); - Expression* property = - factory()->NewProperty(iterator_proxy, literal, nopos); - Expression* throw_proxy = factory()->NewVariableProxy(var_throw); - Expression* assignment = - factory()->NewAssignment(Token::ASSIGN, throw_proxy, property, nopos); - get_throw = factory()->NewExpressionStatement(assignment, nopos); - } - - // if (IS_NULL_OR_UNDEFINED(iteratorThrow) { - // IteratorClose(iterator); - // throw MakeTypeError(kThrowMethodMissing); - // } - Statement* check_throw; - { - Expression* condition = factory()->NewCompareOperation( - Token::EQ, factory()->NewVariableProxy(var_throw), - factory()->NewNullLiteral(nopos), nopos); - Expression* call = - NewThrowTypeError(MessageTemplate::kThrowMethodMissing, - ast_value_factory()->empty_string(), nopos); - Statement* throw_call = factory()->NewExpressionStatement(call, nopos); - - Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos); - BuildIteratorCloseForCompletion( - scope(), then->statements(), var_iterator, - factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), type); - then->statements()->Add(throw_call, zone()); - check_throw = factory()->NewIfStatement( - condition, then, factory()->NewEmptyStatement(nopos), nopos); - } - - // output = %_Call(iteratorThrow, iterator, input); - Statement* call_throw; - { - auto args = new (zone()) ZoneList<Expression*>(3, zone()); - args->Add(factory()->NewVariableProxy(var_throw), zone()); - args->Add(factory()->NewVariableProxy(var_iterator), zone()); - args->Add(factory()->NewVariableProxy(var_input), zone()); - Expression* call = - factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); - if (type == IteratorType::kAsync) { - call = factory()->NewAwait(call, nopos); - } - Expression* assignment = factory()->NewAssignment( - Token::ASSIGN, factory()->NewVariableProxy(var_output), call, nopos); - call_throw = factory()->NewExpressionStatement(assignment, nopos); - } - - // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); - Statement* validate_throw_output; - { - Expression* is_receiver_call; - { - auto args = new (zone()) ZoneList<Expression*>(1, zone()); - args->Add(factory()->NewVariableProxy(var_output), zone()); - is_receiver_call = - factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); - } - - Statement* throw_call; - { - auto args = new (zone()) ZoneList<Expression*>(1, zone()); - args->Add(factory()->NewVariableProxy(var_output), zone()); - Expression* call = factory()->NewCallRuntime( - Runtime::kThrowIteratorResultNotAnObject, args, nopos); - throw_call = factory()->NewExpressionStatement(call, nopos); - } - - validate_throw_output = factory()->NewIfStatement( - is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call, - nopos); - } - - // if (output.done) break; - Statement* if_done; - { - Expression* output_proxy = factory()->NewVariableProxy(var_output); - Expression* literal = - factory()->NewStringLiteral(ast_value_factory()->done_string(), nopos); - Expression* property = factory()->NewProperty(output_proxy, literal, nopos); - BreakStatement* break_loop = factory()->NewBreakStatement(loop, nopos); - if_done = factory()->NewIfStatement( - property, break_loop, factory()->NewEmptyStatement(nopos), nopos); - } - - // Yield(output); - Statement* yield_output; - { - Expression* output_proxy = factory()->NewVariableProxy(var_output); - Suspend* yield = - factory()->NewYield(output_proxy, nopos, Suspend::kNoControl); - yield_output = factory()->NewExpressionStatement(yield, nopos); - } - - // mode = %GeneratorGetResumeMode(); - Statement* get_mode; - { - Expression* mode_proxy = factory()->NewVariableProxy(var_mode); - - ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); - VariableProxy* generator = factory()->NewVariableProxy( - function_state_->scope()->generator_object_var()); - args->Add(generator, zone()); - Expression* mode = factory()->NewCallRuntime( - Runtime::kInlineGeneratorGetResumeMode, args, pos); - - Expression* assignment = - factory()->NewAssignment(Token::ASSIGN, mode_proxy, mode, nopos); - get_mode = factory()->NewExpressionStatement(assignment, nopos); - } - - // input = function.sent; - Statement* get_input; - { - Expression* function_sent = FunctionSentExpression(nopos); - Expression* input_proxy = factory()->NewVariableProxy(var_input); - Expression* assignment = factory()->NewAssignment( - Token::ASSIGN, input_proxy, function_sent, nopos); - get_input = factory()->NewExpressionStatement(assignment, nopos); - } - - // if (mode === kReturn) { - // return {value: output.value, done: true}; - // } - Statement* maybe_return_value; - { - Expression* mode_proxy = factory()->NewVariableProxy(var_mode); - Expression* kreturn = - factory()->NewSmiLiteral(JSGeneratorObject::kReturn, nopos); - Expression* condition = factory()->NewCompareOperation( - Token::EQ_STRICT, mode_proxy, kreturn, nopos); - - Expression* output_proxy = factory()->NewVariableProxy(var_output); - Expression* literal = - factory()->NewStringLiteral(ast_value_factory()->value_string(), nopos); - Expression* property = factory()->NewProperty(output_proxy, literal, nopos); - Statement* return_value = BuildReturnStatement(property, nopos); - - maybe_return_value = factory()->NewIfStatement( - condition, return_value, factory()->NewEmptyStatement(nopos), nopos); - } - - // output.value - Statement* get_value; - { - Expression* output_proxy = factory()->NewVariableProxy(var_output); - Expression* literal = - factory()->NewStringLiteral(ast_value_factory()->value_string(), nopos); - Expression* property = factory()->NewProperty(output_proxy, literal, nopos); - get_value = factory()->NewExpressionStatement(property, nopos); - } - - // Now put things together. - - // switch (mode) { ... } - SwitchStatement* switch_mode = factory()->NewSwitchStatement(nullptr, nopos); - { - auto case_next = new (zone()) ZoneList<Statement*>(3, zone()); - case_next->Add(call_next, zone()); - case_next->Add(validate_next_output, zone()); - case_next->Add(factory()->NewBreakStatement(switch_mode, nopos), zone()); - - auto case_return = new (zone()) ZoneList<Statement*>(5, zone()); - BuildIteratorClose(case_return, var_iterator, var_input, var_output, type); - case_return->Add(factory()->NewBreakStatement(switch_mode, nopos), zone()); - - auto case_throw = new (zone()) ZoneList<Statement*>(5, zone()); - case_throw->Add(get_throw, zone()); - case_throw->Add(check_throw, zone()); - case_throw->Add(call_throw, zone()); - case_throw->Add(validate_throw_output, zone()); - case_throw->Add(factory()->NewBreakStatement(switch_mode, nopos), zone()); - - auto cases = new (zone()) ZoneList<CaseClause*>(3, zone()); - Expression* knext = - factory()->NewSmiLiteral(JSGeneratorObject::kNext, nopos); - Expression* kreturn = - factory()->NewSmiLiteral(JSGeneratorObject::kReturn, nopos); - Expression* kthrow = - factory()->NewSmiLiteral(JSGeneratorObject::kThrow, nopos); - cases->Add(factory()->NewCaseClause(knext, case_next, nopos), zone()); - cases->Add(factory()->NewCaseClause(kreturn, case_return, nopos), zone()); - cases->Add(factory()->NewCaseClause(kthrow, case_throw, nopos), zone()); - - switch_mode->Initialize(factory()->NewVariableProxy(var_mode), cases); - } - - // while (true) { ... } - // Already defined earlier: WhileStatement* loop = ... - { - Block* loop_body = factory()->NewBlock(nullptr, 5, false, nopos); - loop_body->statements()->Add(switch_mode, zone()); - loop_body->statements()->Add(if_done, zone()); - - if (is_async_generator()) { - // AsyncGeneratorYield does not yield the original iterator result, - // unlike sync generators. Do `output = output.value` - VariableProxy* output_proxy = factory()->NewVariableProxy(var_output); - Expression* literal = factory()->NewStringLiteral( - ast_value_factory()->value_string(), nopos); - Assignment* assign = factory()->NewAssignment( - Token::ASSIGN, output_proxy, - factory()->NewProperty(factory()->NewVariableProxy(var_output), - literal, nopos), - nopos); - loop_body->statements()->Add( - factory()->NewExpressionStatement(assign, nopos), zone()); - } - - loop_body->statements()->Add(yield_output, zone()); - loop_body->statements()->Add(get_input, zone()); - loop_body->statements()->Add(get_mode, zone()); - - loop->Initialize(factory()->NewBooleanLiteral(true, nopos), loop_body); - } - - // do { ... } - DoExpression* yield_star; - { - // The rewriter needs to process the get_value statement only, hence we - // put the preceding statements into an init block. - - Block* do_block_ = factory()->NewBlock(nullptr, 6, true, nopos); - do_block_->statements()->Add(initialize_input, zone()); - do_block_->statements()->Add(initialize_mode, zone()); - do_block_->statements()->Add(initialize_output, zone()); - do_block_->statements()->Add(get_iterator, zone()); - do_block_->statements()->Add(loop, zone()); - do_block_->statements()->Add(maybe_return_value, zone()); - - Block* do_block = factory()->NewBlock(nullptr, 2, false, nopos); - do_block->statements()->Add(do_block_, zone()); - do_block->statements()->Add(get_value, zone()); - - Variable* dot_result = - NewTemporary(ast_value_factory()->dot_result_string()); - yield_star = factory()->NewDoExpression(do_block, dot_result, nopos); - Rewriter::Rewrite(this, GetClosureScope(), yield_star, ast_value_factory()); - } - - return yield_star; -} - Statement* Parser::CheckCallable(Variable* var, Expression* error, int pos) { const int nopos = kNoSourcePosition; Statement* validate_var; @@ -4693,10 +4133,9 @@ void Parser::BuildIteratorClose(ZoneList<Statement*>* statements, statements->Add(validate_output, zone()); } -void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, - Expression* condition, Variable* iter, - Block* iterator_use, Block* target, - IteratorType type) { +void Parser::FinalizeIteratorUse(Variable* completion, Expression* condition, + Variable* iter, Block* iterator_use, + Block* target, IteratorType type) { // // This function adds two statements to [target], corresponding to the // following code: @@ -4750,10 +4189,9 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, // } Block* maybe_close; { - Block* block = factory()->NewBlock(nullptr, 2, true, nopos); + Block* block = factory()->NewBlock(2, true); Expression* proxy = factory()->NewVariableProxy(completion); - BuildIteratorCloseForCompletion(use_scope, block->statements(), iter, proxy, - type); + BuildIteratorCloseForCompletion(block->statements(), iter, proxy, type); DCHECK(block->statements()->length() == 2); maybe_close = IgnoreCompletion(factory()->NewIfStatement( @@ -4767,7 +4205,7 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, // } Statement* try_catch; { - Scope* catch_scope = NewHiddenCatchScopeWithParent(use_scope); + Scope* catch_scope = NewHiddenCatchScope(); Statement* rethrow; // We use %ReThrow rather than the ordinary throw because we want to @@ -4782,7 +4220,7 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, factory()->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos); } - Block* catch_block = factory()->NewBlock(nullptr, 2, false, nopos); + Block* catch_block = factory()->NewBlock(2, false); catch_block->statements()->Add(set_completion_throw, zone()); catch_block->statements()->Add(rethrow, zone()); @@ -4793,7 +4231,7 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, // try { #try_catch } finally { #maybe_close } Statement* try_finally; { - Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); + Block* try_block = factory()->NewBlock(1, false); try_block->statements()->Add(try_catch, zone()); try_finally = @@ -4804,8 +4242,7 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, target->statements()->Add(try_finally, zone()); } -void Parser::BuildIteratorCloseForCompletion(Scope* scope, - ZoneList<Statement*>* statements, +void Parser::BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements, Variable* iterator, Expression* completion, IteratorType type) { @@ -4878,12 +4315,12 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope, call = factory()->NewAwait(call, nopos); } - Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); + Block* try_block = factory()->NewBlock(1, false); try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos), zone()); - Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos); - Scope* catch_scope = NewHiddenCatchScopeWithParent(scope); + Block* catch_block = factory()->NewBlock(0, false); + Scope* catch_scope = NewHiddenCatchScope(); try_call_return = factory()->NewTryCatchStatement(try_block, catch_scope, catch_block, nopos); } @@ -4933,7 +4370,7 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope, is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call, nopos); - validate_return = factory()->NewBlock(nullptr, 2, false, nopos); + validate_return = factory()->NewBlock(2, false); validate_return->statements()->Add(call_return, zone()); validate_return->statements()->Add(check_return, zone()); } @@ -4950,7 +4387,7 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope, Token::EQ_STRICT, completion, factory()->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos); - Block* then_block = factory()->NewBlock(nullptr, 2, false, nopos); + Block* then_block = factory()->NewBlock(2, false); then_block->statements()->Add(check_return_callable, zone()); then_block->statements()->Add(try_call_return, zone()); @@ -5009,58 +4446,18 @@ Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop, closing_condition = factory()->NewUnaryOperation(Token::NOT, cmp, nopos); } - Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos); + Block* final_loop = factory()->NewBlock(2, false); { - Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); + Block* try_block = factory()->NewBlock(1, false); try_block->statements()->Add(loop, zone()); - // The scope in which the parser creates this loop. - Scope* loop_scope = scope()->outer_scope(); - DCHECK_EQ(loop_scope->scope_type(), BLOCK_SCOPE); - DCHECK_EQ(scope()->scope_type(), BLOCK_SCOPE); - - FinalizeIteratorUse(loop_scope, var_completion, closing_condition, - loop->iterator(), try_block, final_loop, type); + FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(), + try_block, final_loop, type); } return final_loop; } -void Parser::StitchAst(ParseInfo* top_level_parse_info, Isolate* isolate) { - if (literals_to_stitch_.empty()) return; - std::map<int, ParseInfo*> child_infos = top_level_parse_info->child_infos(); - DCHECK(std::is_sorted(literals_to_stitch_.begin(), literals_to_stitch_.end(), - [](FunctionLiteral* a, FunctionLiteral* b) { - return a->start_position() < b->start_position(); - })); - auto it = literals_to_stitch_.begin(); - for (auto& child_info : child_infos) { - ParseInfo* result = child_info.second; - // If the parse task failed the function will be treated as lazy function - // and reparsed before it gets called - if (!result) continue; - result->UpdateStatisticsAfterBackgroundParse(isolate); - if (!result->literal()) continue; - while ((*it)->start_position() != child_info.first) { - if (++it == literals_to_stitch_.end()) { - return; - } - } - FunctionLiteral* literal = *it; - // FIXME(wiktorg) better handling of default params for arrow functions - Scope* outer_scope = literal->scope()->outer_scope(); - if (outer_scope->is_declaration_scope() && - outer_scope->AsDeclarationScope()->was_lazily_parsed()) { - continue; - } - // TODO(wiktorg) in the future internalize somewhere else (stitching may be - // done on streamer thread) - result->ast_value_factory()->Internalize(isolate); - literal->ReplaceBodyAndScope(result->literal()); - literal->SetShouldEagerCompile(); - } -} - #undef CHECK_OK #undef CHECK_OK_VOID #undef CHECK_FAILED |