summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/parser.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-03-21 10:16:54 +0100
committerMichaël Zasso <targos@protonmail.com>2017-03-25 09:44:10 +0100
commitc459d8ea5d402c702948c860d9497b2230ff7e8a (patch)
tree56c282fc4d40e5cb613b47cf7be3ea0526ed5b6f /deps/v8/src/parsing/parser.cc
parente0bc5a7361b1d29c3ed034155fd779ce6f44fb13 (diff)
downloadandroid-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.tar.gz
android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.tar.bz2
android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.zip
deps: update V8 to 5.7.492.69
PR-URL: https://github.com/nodejs/node/pull/11752 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing/parser.cc')
-rw-r--r--deps/v8/src/parsing/parser.cc875
1 files changed, 272 insertions, 603 deletions
diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc
index 3ed7af267e..bcafd78853 100644
--- a/deps/v8/src/parsing/parser.cc
+++ b/deps/v8/src/parsing/parser.cc
@@ -8,6 +8,7 @@
#include "src/api.h"
#include "src/ast/ast-expression-rewriter.h"
+#include "src/ast/ast-function-literal-id-reindexer.h"
#include "src/ast/ast-literal-reindexer.h"
#include "src/ast/ast-traversal-visitor.h"
#include "src/ast/ast.h"
@@ -15,6 +16,7 @@
#include "src/base/platform/platform.h"
#include "src/char-predicates-inl.h"
#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/parse-info.h"
@@ -112,8 +114,13 @@ class DiscardableZoneScope {
fni_(parser->ast_value_factory_, temp_zone),
parser_(parser),
prev_fni_(parser->fni_),
- prev_zone_(parser->zone_) {
+ prev_zone_(parser->zone_),
+ prev_allow_lazy_(parser->allow_lazy_),
+ prev_temp_zoned_(parser->temp_zoned_) {
if (use_temp_zone) {
+ DCHECK(!parser_->temp_zoned_);
+ parser_->allow_lazy_ = false;
+ parser_->temp_zoned_ = true;
parser_->fni_ = &fni_;
parser_->zone_ = temp_zone;
if (parser_->reusable_preparser_ != nullptr) {
@@ -125,6 +132,8 @@ class DiscardableZoneScope {
void Reset() {
parser_->fni_ = prev_fni_;
parser_->zone_ = prev_zone_;
+ parser_->allow_lazy_ = prev_allow_lazy_;
+ parser_->temp_zoned_ = prev_temp_zoned_;
if (parser_->reusable_preparser_ != nullptr) {
parser_->reusable_preparser_->zone_ = prev_zone_;
parser_->reusable_preparser_->factory()->set_zone(prev_zone_);
@@ -139,6 +148,8 @@ class DiscardableZoneScope {
Parser* parser_;
FuncNameInferrer* prev_fni_;
Zone* prev_zone_;
+ bool prev_allow_lazy_;
+ bool prev_temp_zoned_;
DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope);
};
@@ -146,82 +157,26 @@ class DiscardableZoneScope {
void Parser::SetCachedData(ParseInfo* info) {
DCHECK_NULL(cached_parse_data_);
if (consume_cached_parse_data()) {
- cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
- if (cached_parse_data_ == nullptr) {
- compile_options_ = ScriptCompiler::kNoCompileOptions;
+ if (allow_lazy_) {
+ cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
+ if (cached_parse_data_ != nullptr) return;
}
+ compile_options_ = ScriptCompiler::kNoCompileOptions;
}
}
-Expression* Parser::CallClassFieldInitializer(Scope* scope,
- Expression* this_expr) {
- // This produces the expression
- // `.class_field_intializer(this_expr)`, where '.class_field_intializer' is
- // the name
- // of a synthetic variable.
- // 'this_expr' will be 'this' in a base constructor and the result of calling
- // 'super' in a derived one.
- const AstRawString* init_fn_name =
- ast_value_factory()->dot_class_field_init_string();
- VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name);
- ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
- args->Add(init_fn_proxy, zone());
- args->Add(this_expr, zone());
- return factory()->NewCallRuntime(Runtime::kInlineCall, args,
- kNoSourcePosition);
-}
-
-Expression* Parser::RewriteSuperCall(Expression* super_call) {
- // TODO(bakkot) find a way to avoid this for classes without fields.
- if (!allow_harmony_class_fields()) {
- return super_call;
- }
- // This turns a super call `super()` into a do expression of the form
- // do {
- // tmp x = super();
- // if (.class-field-init)
- // .class-field-init(x)
- // x; // This isn't actually present; our do-expression representation
- // allows specifying that the expression returns x directly.
- // }
- Variable* var_tmp =
- scope()->NewTemporary(ast_value_factory()->empty_string());
- Block* block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
- Assignment* assignment = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(var_tmp), super_call,
- kNoSourcePosition);
- block->statements()->Add(
- factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
- const AstRawString* init_fn_name =
- ast_value_factory()->dot_class_field_init_string();
- VariableProxy* init_fn_proxy =
- scope()->NewUnresolved(factory(), init_fn_name);
- Expression* condition = init_fn_proxy;
- Statement* initialize = factory()->NewExpressionStatement(
- CallClassFieldInitializer(scope(), factory()->NewVariableProxy(var_tmp)),
- kNoSourcePosition);
- IfStatement* if_statement = factory()->NewIfStatement(
- condition, initialize, factory()->NewEmptyStatement(kNoSourcePosition),
- kNoSourcePosition);
- block->statements()->Add(if_statement, zone());
- return factory()->NewDoExpression(block, var_tmp, kNoSourcePosition);
-}
-
FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
- bool call_super,
- bool requires_class_field_init,
- int pos, int end_pos,
- LanguageMode language_mode) {
+ bool call_super, int pos,
+ int end_pos) {
int materialized_literal_count = -1;
int expected_property_count = -1;
const int parameter_count = 0;
if (name == nullptr) name = ast_value_factory()->empty_string();
- FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
+ FunctionKind kind = call_super ? FunctionKind::kDefaultDerivedConstructor
: FunctionKind::kDefaultBaseConstructor;
DeclarationScope* function_scope = NewFunctionScope(kind);
- SetLanguageMode(function_scope,
- static_cast<LanguageMode>(language_mode | STRICT));
+ SetLanguageMode(function_scope, STRICT);
// Set start and end position to the same value
function_scope->set_start_position(pos);
function_scope->set_end_position(pos);
@@ -233,9 +188,7 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
if (call_super) {
- // $super_constructor = %_GetSuperConstructor(<this-function>)
- // %reflect_construct(
- // $super_constructor, InternalArray(...args), new.target)
+ // Create a SuperCallReference and handle in BytecodeGenerator.
auto constructor_args_name = ast_value_factory()->empty_string();
bool is_duplicate;
bool is_rest = true;
@@ -245,29 +198,13 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
ast_value_factory());
ZoneList<Expression*>* args =
- new (zone()) ZoneList<Expression*>(2, zone());
- VariableProxy* this_function_proxy =
- NewUnresolved(ast_value_factory()->this_function_string(), pos);
- ZoneList<Expression*>* tmp =
new (zone()) ZoneList<Expression*>(1, zone());
- tmp->Add(this_function_proxy, zone());
- Expression* super_constructor = factory()->NewCallRuntime(
- Runtime::kInlineGetSuperConstructor, tmp, pos);
- args->Add(super_constructor, zone());
Spread* spread_args = factory()->NewSpread(
factory()->NewVariableProxy(constructor_args), pos, pos);
- ZoneList<Expression*>* spread_args_expr =
- new (zone()) ZoneList<Expression*>(1, zone());
- spread_args_expr->Add(spread_args, zone());
- args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone());
- VariableProxy* new_target_proxy =
- NewUnresolved(ast_value_factory()->new_target_string(), pos);
- args->Add(new_target_proxy, zone());
- Expression* call = factory()->NewCallRuntime(
- Context::REFLECT_CONSTRUCT_INDEX, args, pos);
- if (requires_class_field_init) {
- call = CallClassFieldInitializer(scope(), call);
- }
+
+ args->Add(spread_args, zone());
+ Expression* super_call_ref = NewSuperCallReference(pos);
+ Expression* call = factory()->NewCall(super_call_ref, args, pos);
body->Add(factory()->NewReturnStatement(call, pos), zone());
}
@@ -280,9 +217,7 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
expected_property_count, parameter_count, parameter_count,
FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::kAnonymousExpression, default_eager_compile_hint(), pos,
- true);
-
- function_literal->set_requires_class_field_init(requires_class_field_init);
+ true, GetNextFunctionLiteralId());
return function_literal;
}
@@ -511,15 +446,6 @@ Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
return NULL;
}
-Expression* Parser::GetIterator(Expression* iterable, int pos) {
- Expression* iterator_symbol_literal =
- factory()->NewSymbolLiteral("iterator_symbol", kNoSourcePosition);
- Expression* prop =
- factory()->NewProperty(iterable, iterator_symbol_literal, pos);
- ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone());
- return factory()->NewCall(prop, args, pos);
-}
-
void Parser::MarkTailPosition(Expression* expression) {
expression->MarkTail();
}
@@ -582,7 +508,8 @@ 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->isolate()->counters()->runtime_call_stats()),
+ info->isolate()->counters()->runtime_call_stats(),
+ true),
scanner_(info->unicode_cache()),
reusable_preparser_(nullptr),
original_scope_(nullptr),
@@ -591,7 +518,7 @@ Parser::Parser(ParseInfo* info)
compile_options_(info->compile_options()),
cached_parse_data_(nullptr),
total_preparse_skipped_(0),
- parsing_on_main_thread_(true),
+ temp_zoned_(false),
log_(nullptr) {
// Even though we were passed ParseInfo, we should not store it in
// Parser - this makes sure that Isolate is not accidentally accessed via
@@ -615,25 +542,25 @@ Parser::Parser(ParseInfo* info)
set_default_eager_compile_hint(can_compile_lazily
? FunctionLiteral::kShouldLazyCompile
: FunctionLiteral::kShouldEagerCompile);
- set_allow_lazy(FLAG_lazy && info->allow_lazy_parsing() &&
- !info->is_native() && info->extension() == nullptr &&
- can_compile_lazily);
+ allow_lazy_ = FLAG_lazy && info->allow_lazy_parsing() && !info->is_native() &&
+ info->extension() == nullptr && can_compile_lazily;
set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
info->isolate()->is_tail_call_elimination_enabled());
set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
set_allow_harmony_function_sent(FLAG_harmony_function_sent);
- set_allow_harmony_async_await(FLAG_harmony_async_await);
set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators);
set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas);
set_allow_harmony_class_fields(FLAG_harmony_class_fields);
+ set_allow_harmony_object_spread(FLAG_harmony_object_spread);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++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->hash_seed()));
+ info->set_ast_value_factory(new AstValueFactory(
+ zone(), info->isolate()->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_);
@@ -665,7 +592,6 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* 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_, info->is_eval() ? &RuntimeCallStats::ParseEval
: &RuntimeCallStats::ParseProgram);
@@ -682,7 +608,11 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
ParserLogger logger;
if (produce_cached_parse_data()) {
- log_ = &logger;
+ if (allow_lazy_) {
+ log_ = &logger;
+ } else {
+ compile_options_ = ScriptCompiler::kNoCompileOptions;
+ }
} else if (consume_cached_parse_data()) {
cached_parse_data_->Initialize();
}
@@ -730,7 +660,10 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
DCHECK_NULL(scope_state_);
DCHECK_NULL(target_stack_);
- ParsingModeScope mode(this, allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY);
+ ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY);
+ ResetFunctionLiteralId();
+ DCHECK(info->function_literal_id() == FunctionLiteral::kIdTypeTopLevel ||
+ info->function_literal_id() == FunctionLiteral::kIdTypeInvalid);
FunctionLiteral* result = NULL;
{
@@ -764,7 +697,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
DCHECK(!is_duplicate);
var->AllocateTo(VariableLocation::PARAMETER, 0);
- PrepareGeneratorVariables(&function_state);
+ PrepareGeneratorVariables();
Expression* initial_yield =
BuildInitialYield(kNoSourcePosition, kGeneratorFunction);
body->Add(
@@ -788,8 +721,6 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
if (ok && is_strict(language_mode())) {
CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
- CheckDecimalLiteralWithLeadingZero(beg_pos,
- scanner()->location().end_pos);
}
if (ok && is_sloppy(language_mode())) {
// TODO(littledan): Function bindings on the global object that modify
@@ -821,6 +752,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
}
}
+ info->set_max_function_literal_id(GetLastFunctionLiteralId());
+
// Make sure the target stack is empty.
DCHECK(target_stack_ == NULL);
@@ -842,6 +775,12 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info) {
}
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();
+ factory()->set_zone(info->zone());
+ } else {
+ DCHECK_EQ(factory()->zone(), info->zone());
+ }
// Initialize parser state.
source = String::Flatten(source);
@@ -891,6 +830,10 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
fni_->PushEnclosingName(raw_name);
+ ResetFunctionLiteralId();
+ DCHECK_LT(0, info->function_literal_id());
+ SkipFunctionLiterals(info->function_literal_id() - 1);
+
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
// Place holder for the result.
@@ -911,7 +854,7 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
bool ok = true;
if (IsArrowFunction(kind)) {
- if (allow_harmony_async_await() && IsAsyncFunction(kind)) {
+ if (IsAsyncFunction(kind)) {
DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
if (!Check(Token::ASYNC)) {
CHECK(stack_overflow());
@@ -951,12 +894,27 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
} else {
// BindingIdentifier
ParseFormalParameter(&formals, &ok);
- if (ok) DeclareFormalParameter(formals.scope, formals.at(0));
+ if (ok) DeclareFormalParameters(formals.scope, formals.params);
}
}
if (ok) {
checkpoint.Restore(&formals.materialized_literals_count);
+ if (GetLastFunctionLiteralId() != info->function_literal_id() - 1) {
+ // If there were FunctionLiterals in the parameters, we need to
+ // renumber them to shift down so the next function literal id for
+ // the arrow function is the one requested.
+ AstFunctionLiteralIdReindexer reindexer(
+ stack_limit_,
+ (info->function_literal_id() - 1) - GetLastFunctionLiteralId());
+ for (auto p : formals.params) {
+ if (p->pattern != nullptr) reindexer.Reindex(p->pattern);
+ if (p->initializer != nullptr) reindexer.Reindex(p->initializer);
+ }
+ ResetFunctionLiteralId();
+ SkipFunctionLiterals(info->function_literal_id() - 1);
+ }
+
// Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
// not be observable, or else the preparser would have failed.
Expression* expression = ParseArrowFunctionLiteral(true, formals, &ok);
@@ -979,29 +937,12 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
}
} else if (IsDefaultConstructor(kind)) {
DCHECK_EQ(scope(), outer);
- bool is_subclass_constructor = IsSubclassConstructor(kind);
- result = DefaultConstructor(
- raw_name, is_subclass_constructor, info->requires_class_field_init(),
- info->start_position(), info->end_position(), info->language_mode());
- if (!is_subclass_constructor && info->requires_class_field_init()) {
- result = InsertClassFieldInitializer(result);
- }
- } else if (info->is_class_field_initializer()) {
- Handle<SharedFunctionInfo> shared_info = info->shared_info();
- DCHECK(!shared_info.is_null());
- if (shared_info->length() == 0) {
- result = ParseClassFieldForInitializer(
- info->start_position() != info->end_position(), &ok);
- } else {
- result = SynthesizeClassFieldInitializer(shared_info->length());
- }
+ result = DefaultConstructor(raw_name, IsDerivedConstructor(kind),
+ info->start_position(), info->end_position());
} else {
result = ParseFunctionLiteral(
raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind,
kNoSourcePosition, function_type, info->language_mode(), &ok);
- if (info->requires_class_field_init()) {
- result = InsertClassFieldInitializer(result);
- }
}
// Make sure the results agree.
DCHECK(ok == (result != nullptr));
@@ -1009,6 +950,8 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
// Make sure the target stack is empty.
DCHECK_NULL(target_stack_);
+ DCHECK_IMPLIES(result,
+ info->function_literal_id() == result->function_literal_id());
return result;
}
@@ -1290,7 +1233,7 @@ Statement* Parser::ParseExportDefault(bool* ok) {
break;
case Token::ASYNC:
- if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
+ if (PeekAhead() == Token::FUNCTION &&
!scanner()->HasAnyLineTerminatorAfterNext()) {
Consume(Token::ASYNC);
result = ParseAsyncFunctionDeclaration(&local_names, true, CHECK_OK);
@@ -1423,14 +1366,11 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
break;
case Token::ASYNC:
- if (allow_harmony_async_await()) {
- // TODO(neis): Why don't we have the same check here as in
- // ParseStatementListItem?
- Consume(Token::ASYNC);
- result = ParseAsyncFunctionDeclaration(&names, false, CHECK_OK);
- break;
- }
- /* falls through */
+ // TODO(neis): Why don't we have the same check here as in
+ // ParseStatementListItem?
+ Consume(Token::ASYNC);
+ result = ParseAsyncFunctionDeclaration(&names, false, CHECK_OK);
+ break;
default:
*ok = false;
@@ -1533,15 +1473,11 @@ void Parser::DeclareAndInitializeVariables(
}
Statement* Parser::DeclareFunction(const AstRawString* variable_name,
- FunctionLiteral* function, int pos,
- bool is_generator, bool is_async,
+ FunctionLiteral* function, VariableMode mode,
+ int pos, bool is_generator, bool is_async,
+ bool is_sloppy_block_function,
ZoneList<const AstRawString*>* names,
bool* ok) {
- // In ES6, a function behaves as a lexical binding, except in
- // a script scope, or the initial scope of eval or another function.
- VariableMode mode =
- (!scope()->is_declaration_scope() || scope()->is_module_scope()) ? LET
- : VAR;
VariableProxy* proxy =
factory()->NewVariableProxy(variable_name, NORMAL_VARIABLE);
Declaration* declaration =
@@ -1549,18 +1485,12 @@ Statement* Parser::DeclareFunction(const AstRawString* variable_name,
Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
CHECK_OK);
if (names) names->Add(variable_name, zone());
- // Async functions don't undergo sloppy mode block scoped hoisting, and don't
- // allow duplicates in a block. Both are represented by the
- // sloppy_block_function_map. Don't add them to the map for async functions.
- // Generators are also supposed to be prohibited; currently doing this behind
- // a flag and UseCounting violations to assess web compatibility.
- if (is_sloppy(language_mode()) && !scope()->is_declaration_scope() &&
- !is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
- SloppyBlockFunctionStatement* delegate =
- factory()->NewSloppyBlockFunctionStatement(scope());
+ if (is_sloppy_block_function) {
+ SloppyBlockFunctionStatement* statement =
+ factory()->NewSloppyBlockFunctionStatement();
DeclarationScope* target_scope = GetDeclarationScope();
- target_scope->DeclareSloppyBlockFunction(variable_name, delegate);
- return delegate;
+ target_scope->DeclareSloppyBlockFunction(variable_name, scope(), statement);
+ return statement;
}
return factory()->NewEmptyStatement(kNoSourcePosition);
}
@@ -1601,6 +1531,7 @@ Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) {
ZoneList<const AstRawString*>* Parser::DeclareLabel(
ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) {
+ DCHECK(IsIdentifier(var));
const AstRawString* label = var->raw_name();
// TODO(1240780): We don't check for redeclaration of labels
// during preparsing since keeping track of the set of active
@@ -1635,7 +1566,7 @@ bool Parser::ContainsLabel(ZoneList<const AstRawString*>* labels,
}
Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
- if (IsSubclassConstructor(function_state_->kind())) {
+ if (IsDerivedConstructor(function_state_->kind())) {
// For subclass constructors we need to return this in case of undefined
// return a Smi (transformed into an exception in the ConstructStub)
// for a non object.
@@ -1742,8 +1673,7 @@ void Parser::RewriteCatchPattern(CatchInfo* catch_info, bool* ok) {
DCHECK_NOT_NULL(catch_info->pattern);
catch_info->name = ast_value_factory()->dot_catch_string();
}
- catch_info->variable = catch_info->scope->DeclareLocal(
- catch_info->name, VAR, kCreatedInitialized, NORMAL_VARIABLE);
+ catch_info->variable = catch_info->scope->DeclareLocal(catch_info->name, VAR);
if (catch_info->pattern != nullptr) {
DeclarationDescriptor descriptor;
descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
@@ -1802,15 +1732,9 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
DCHECK_NOT_NULL(catch_info.scope);
DCHECK_NOT_NULL(catch_info.variable);
TryCatchStatement* statement;
- if (catch_info.for_promise_reject) {
- statement = factory()->NewTryCatchStatementForPromiseReject(
- try_block, catch_info.scope, catch_info.variable, catch_block,
- kNoSourcePosition);
- } else {
- statement = factory()->NewTryCatchStatement(
- try_block, catch_info.scope, catch_info.variable, catch_block,
- kNoSourcePosition);
- }
+ statement = factory()->NewTryCatchStatement(try_block, catch_info.scope,
+ catch_info.variable,
+ catch_block, kNoSourcePosition);
try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
try_block->statements()->Add(statement, zone());
@@ -1897,6 +1821,7 @@ Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt,
body = block;
each = factory()->NewVariableProxy(temp);
}
+ MarkExpressionAsAssigned(each);
stmt->AsForInStatement()->Initialize(each, subject, body);
}
return stmt;
@@ -1958,6 +1883,7 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
Block** body_block,
Expression** each_variable,
bool* ok) {
+ DCHECK(for_info->parsing_result.declarations.length() == 1);
DeclarationParsingResult::Declaration& decl =
for_info->parsing_result.declarations[0];
Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
@@ -2046,16 +1972,17 @@ Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
const int nopos = kNoSourcePosition;
auto avfactory = ast_value_factory();
- Variable* iterator = NewTemporary(ast_value_factory()->dot_iterator_string());
- Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
+ Variable* iterator = NewTemporary(avfactory->dot_iterator_string());
+ Variable* result = NewTemporary(avfactory->dot_result_string());
Variable* completion = NewTemporary(avfactory->empty_string());
- // iterator = iterable[Symbol.iterator]()
+ // iterator = GetIterator(iterable)
Expression* assign_iterator;
{
assign_iterator = factory()->NewAssignment(
Token::ASSIGN, factory()->NewVariableProxy(iterator),
- GetIterator(iterable, iterable->position()), iterable->position());
+ factory()->NewGetIterator(iterable, iterable->position()),
+ iterable->position());
}
// !%_IsJSReceiver(result = iterator.next()) &&
@@ -2467,15 +2394,11 @@ void Parser::DeclareArrowFunctionFormalParameters(
if (!parameters->is_simple) {
this->classifier()->RecordNonSimpleParameter();
}
- for (int i = 0; i < parameters->arity; ++i) {
- auto parameter = parameters->at(i);
- DeclareFormalParameter(parameters->scope, parameter);
- if (!this->classifier()
- ->is_valid_formal_parameter_list_without_duplicates() &&
- !duplicate_loc->IsValid()) {
- *duplicate_loc =
- this->classifier()->duplicate_formal_parameter_error().location;
- }
+ DeclareFormalParameters(parameters->scope, parameters->params);
+ if (!this->classifier()
+ ->is_valid_formal_parameter_list_without_duplicates()) {
+ *duplicate_loc =
+ this->classifier()->duplicate_formal_parameter_error().location;
}
DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
}
@@ -2484,28 +2407,28 @@ void Parser::ReindexLiterals(const ParserFormalParameters& parameters) {
if (function_state_->materialized_literal_count() > 0) {
AstLiteralReindexer reindexer;
- for (const auto p : parameters.params) {
- if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
- if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
+ for (auto p : parameters.params) {
+ if (p->pattern != nullptr) reindexer.Reindex(p->pattern);
+ if (p->initializer != nullptr) reindexer.Reindex(p->initializer);
}
DCHECK(reindexer.count() <= function_state_->materialized_literal_count());
}
}
-void Parser::PrepareGeneratorVariables(FunctionState* function_state) {
- // For generators, allocating variables in contexts is currently a win
- // because it minimizes the work needed to suspend and resume an
- // activation. The machine code produced for generators (by full-codegen)
- // relies on this forced context allocation, but not in an essential way.
- scope()->ForceContextAllocation();
+void Parser::PrepareGeneratorVariables() {
+ // For generators, allocating variables in contexts is currently a win because
+ // it minimizes the work needed to suspend and resume an activation. The
+ // code produced for generators relies on this forced context allocation (it
+ // does not restore the frame's parameters upon resume).
+ function_state_->scope()->ForceContextAllocation();
// Calling a generator returns a generator object. That object is stored
// in a temporary variable, a definition that is used by "yield"
// expressions.
Variable* temp =
NewTemporary(ast_value_factory()->dot_generator_object_string());
- function_state->set_generator_object_variable(temp);
+ function_state_->set_generator_object_variable(temp);
}
FunctionLiteral* Parser::ParseFunctionLiteral(
@@ -2536,7 +2459,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
}
FunctionLiteral::EagerCompileHint eager_compile_hint =
- function_state_->next_function_is_parenthesized()
+ function_state_->next_function_is_likely_called()
? FunctionLiteral::kShouldEagerCompile
: default_eager_compile_hint();
@@ -2573,7 +2496,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// immediately). bar can be parsed lazily, but we need to parse it in a mode
// that tracks unresolved variables.
DCHECK_IMPLIES(parse_lazily(), FLAG_lazy);
- DCHECK_IMPLIES(parse_lazily(), allow_lazy());
+ DCHECK_IMPLIES(parse_lazily(), allow_lazy_);
DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr);
bool can_preparse = parse_lazily() &&
@@ -2582,8 +2505,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
bool is_lazy_top_level_function =
can_preparse && impl()->AllowsLazyParsingWithoutUnresolvedVariables();
- RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
- &RuntimeCallStats::ParseFunctionLiteral);
+ RuntimeCallTimerScope runtime_timer(
+ runtime_call_stats_,
+ parsing_on_main_thread_
+ ? &RuntimeCallStats::ParseFunctionLiteral
+ : &RuntimeCallStats::ParseBackgroundFunctionLiteral);
// Determine whether we can still lazy parse the inner function.
// The preconditions are:
@@ -2598,29 +2524,26 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// FunctionExpression; even without enclosing parentheses it might be
// immediately invoked.
// - The function literal shouldn't be hinted to eagerly compile.
- // - For asm.js functions the body needs to be available when module
- // validation is active, because we examine the entire module at once.
// Inner functions will be parsed using a temporary Zone. After parsing, we
// will migrate unresolved variable into a Scope in the main Zone.
// TODO(marja): Refactor parsing modes: simplify this.
bool use_temp_zone =
- (FLAG_lazy_inner_functions
+ (FLAG_aggressive_lazy_inner_functions
? can_preparse
: (is_lazy_top_level_function ||
- (allow_lazy() && function_type == FunctionLiteral::kDeclaration &&
- eager_compile_hint == FunctionLiteral::kShouldLazyCompile))) &&
- !(FLAG_validate_asm && scope()->IsAsmModule());
+ (parse_lazily() &&
+ function_type == FunctionLiteral::kDeclaration &&
+ eager_compile_hint == FunctionLiteral::kShouldLazyCompile)));
+
+ DCHECK_IMPLIES(
+ (is_lazy_top_level_function ||
+ (parse_lazily() && function_type == FunctionLiteral::kDeclaration &&
+ eager_compile_hint == FunctionLiteral::kShouldLazyCompile)),
+ can_preparse);
bool is_lazy_inner_function =
use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function;
- // This Scope lives in the main zone. We'll migrate data into that zone later.
- DeclarationScope* scope = NewFunctionScope(kind);
- SetLanguageMode(scope, language_mode);
-#ifdef DEBUG
- scope->SetScopeName(function_name);
-#endif
-
ZoneList<Statement*>* body = nullptr;
int materialized_literal_count = -1;
int expected_property_count = -1;
@@ -2628,9 +2551,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
int num_parameters = -1;
int function_length = -1;
bool has_duplicate_parameters = false;
+ int function_literal_id = GetNextFunctionLiteralId();
- Expect(Token::LPAREN, CHECK_OK);
- scope->set_start_position(scanner()->location().beg_pos);
+ Zone* outer_zone = zone();
+ DeclarationScope* scope;
{
// Temporary zones can nest. When we migrate free variables (see below), we
@@ -2645,10 +2569,19 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// information when the function is parsed.
Zone temp_zone(zone()->allocator(), ZONE_NAME);
DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone);
+
+ // This Scope lives in the main zone. We'll migrate data into that zone
+ // later.
+ scope = NewFunctionScope(kind, outer_zone);
+ SetLanguageMode(scope, language_mode);
#ifdef DEBUG
+ scope->SetScopeName(function_name);
if (use_temp_zone) 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
// lazily. We'll call SkipFunction, which may decide to
// abort lazy parsing if it suspects that wasn't a good idea. If so (in
@@ -2695,19 +2628,28 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope->AnalyzePartially(&previous_zone_ast_node_factory);
}
+ DCHECK_IMPLIES(use_temp_zone, temp_zoned_);
if (FLAG_trace_preparse) {
PrintF(" [%s]: %i-%i %.*s\n",
is_lazy_top_level_function
? "Preparse no-resolution"
- : (use_temp_zone ? "Preparse resolution" : "Full parse"),
+ : (temp_zoned_ ? "Preparse resolution" : "Full parse"),
scope->start_position(), scope->end_position(),
function_name->byte_length(), function_name->raw_data());
+ }
+ if (V8_UNLIKELY(FLAG_runtime_stats)) {
if (is_lazy_top_level_function) {
- CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_,
- PreParseNoVariableResolution);
- } else if (use_temp_zone) {
- CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_,
- PreParseWithVariableResolution);
+ RuntimeCallStats::CorrectCurrentCounterId(
+ runtime_call_stats_,
+ parsing_on_main_thread_
+ ? &RuntimeCallStats::PreParseNoVariableResolution
+ : &RuntimeCallStats::PreParseBackgroundNoVariableResolution);
+ } else if (temp_zoned_) {
+ RuntimeCallStats::CorrectCurrentCounterId(
+ runtime_call_stats_,
+ parsing_on_main_thread_
+ ? &RuntimeCallStats::PreParseWithVariableResolution
+ : &RuntimeCallStats::PreParseBackgroundWithVariableResolution);
}
}
@@ -2720,8 +2662,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
if (is_strict(language_mode)) {
CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
CHECK_OK);
- CheckDecimalLiteralWithLeadingZero(scope->start_position(),
- scope->end_position());
}
CheckConflictingVarDeclarations(scope, CHECK_OK);
} // DiscardableZoneScope goes out of scope.
@@ -2734,7 +2674,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
function_name, scope, body, materialized_literal_count,
expected_property_count, num_parameters, function_length,
- duplicate_parameters, function_type, eager_compile_hint, pos, true);
+ duplicate_parameters, function_type, eager_compile_hint, pos, true,
+ function_literal_id);
function_literal->set_function_token_position(function_token_pos);
if (should_be_used_once_hint)
function_literal->set_should_be_used_once_hint();
@@ -2782,6 +2723,7 @@ Parser::LazyParsingResult Parser::SkipFunction(
if (entry.uses_super_property())
function_scope->RecordSuperPropertyUsage();
if (entry.calls_eval()) function_scope->RecordEvalCall();
+ SkipFunctionLiterals(entry.num_inner_functions());
return kLazyParsingComplete;
}
cached_parse_data_->Reject();
@@ -2792,17 +2734,16 @@ Parser::LazyParsingResult Parser::SkipFunction(
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
if (reusable_preparser_ == NULL) {
- reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
- &pending_error_handler_,
- runtime_call_stats_, stack_limit_);
- reusable_preparser_->set_allow_lazy(true);
+ reusable_preparser_ = new PreParser(
+ zone(), &scanner_, stack_limit_, ast_value_factory(),
+ &pending_error_handler_, runtime_call_stats_, parsing_on_main_thread_);
#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
SET_ALLOW(natives);
SET_ALLOW(harmony_do_expressions);
SET_ALLOW(harmony_function_sent);
- SET_ALLOW(harmony_async_await);
SET_ALLOW(harmony_trailing_commas);
SET_ALLOW(harmony_class_fields);
+ SET_ALLOW(harmony_object_spread);
#undef SET_ALLOW
}
// Aborting inner function preparsing would leave scopes in an inconsistent
@@ -2835,13 +2776,15 @@ Parser::LazyParsingResult Parser::SkipFunction(
*has_duplicate_parameters = logger->has_duplicate_parameters();
*materialized_literal_count = logger->literals();
*expected_property_count = logger->properties();
+ SkipFunctionLiterals(logger->num_inner_functions());
if (!is_inner_function && produce_cached_parse_data()) {
DCHECK(log_);
log_->LogFunction(
function_scope->start_position(), function_scope->end_position(),
*num_parameters, *function_length, *has_duplicate_parameters,
*materialized_literal_count, *expected_property_count, language_mode(),
- function_scope->uses_super_property(), function_scope->calls_eval());
+ function_scope->uses_super_property(), function_scope->calls_eval(),
+ logger->num_inner_functions());
}
return kLazyParsingComplete;
}
@@ -2890,6 +2833,7 @@ class InitializerRewriter final
if (to_rewrite->is_rewritten()) return;
Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite,
scope_);
+ AstTraversalVisitor::VisitRewritableExpression(to_rewrite);
}
// Code in function literals does not need to be eagerly rewritten, it will be
@@ -2912,44 +2856,44 @@ Block* Parser::BuildParameterInitializationBlock(
DCHECK(!parameters.is_simple);
DCHECK(scope()->is_function_scope());
Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition);
- for (int i = 0; i < parameters.params.length(); ++i) {
- auto parameter = parameters.params[i];
- if (parameter.is_rest && parameter.pattern->IsVariableProxy()) break;
+ int index = 0;
+ for (auto parameter : parameters.params) {
+ if (parameter->is_rest && parameter->pattern->IsVariableProxy()) break;
DeclarationDescriptor descriptor;
descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
descriptor.scope = scope();
descriptor.hoist_scope = nullptr;
descriptor.mode = LET;
- descriptor.declaration_pos = parameter.pattern->position();
+ descriptor.declaration_pos = parameter->pattern->position();
// The position that will be used by the AssignmentExpression
// which copies from the temp parameter to the pattern.
//
// TODO(adamk): Should this be kNoSourcePosition, since
// it's just copying from a temp var to the real param var?
- descriptor.initialization_pos = parameter.pattern->position();
+ descriptor.initialization_pos = parameter->pattern->position();
Expression* initial_value =
- factory()->NewVariableProxy(parameters.scope->parameter(i));
- if (parameter.initializer != nullptr) {
+ factory()->NewVariableProxy(parameters.scope->parameter(index));
+ if (parameter->initializer != nullptr) {
// IS_UNDEFINED($param) ? initializer : $param
// Ensure initializer is rewritten
- RewriteParameterInitializer(parameter.initializer, scope());
+ RewriteParameterInitializer(parameter->initializer, scope());
auto condition = factory()->NewCompareOperation(
Token::EQ_STRICT,
- factory()->NewVariableProxy(parameters.scope->parameter(i)),
+ factory()->NewVariableProxy(parameters.scope->parameter(index)),
factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
initial_value = factory()->NewConditional(
- condition, parameter.initializer, initial_value, kNoSourcePosition);
- descriptor.initialization_pos = parameter.initializer->position();
+ condition, parameter->initializer, initial_value, kNoSourcePosition);
+ descriptor.initialization_pos = parameter->initializer->position();
}
Scope* param_scope = scope();
Block* param_block = init_block;
- if (!parameter.is_simple() && scope()->calls_sloppy_eval()) {
+ if (!parameter->is_simple() && scope()->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->set_end_position(parameter->initializer_end_position);
param_scope->RecordEvalCall();
param_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition);
param_block->set_scope(param_scope);
@@ -2964,7 +2908,7 @@ Block* Parser::BuildParameterInitializationBlock(
BlockState block_state(&scope_state_, param_scope);
DeclarationParsingResult::Declaration decl(
- parameter.pattern, parameter.initializer_end_position, initial_value);
+ parameter->pattern, parameter->initializer_end_position, initial_value);
PatternRewriter::DeclareAndInitializeVariables(
this, param_block, &descriptor, &decl, nullptr, CHECK_OK);
@@ -2975,6 +2919,7 @@ Block* Parser::BuildParameterInitializationBlock(
}
init_block->statements()->Add(param_block, zone());
}
+ ++index;
}
return init_block;
}
@@ -3009,8 +2954,7 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) {
Scope* catch_scope = NewScope(CATCH_SCOPE);
catch_scope->set_is_hidden();
Variable* catch_variable =
- catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
- kCreatedInitialized, NORMAL_VARIABLE);
+ catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
Expression* promise_reject = BuildRejectPromise(
@@ -3049,15 +2993,20 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) {
return result;
}
-Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
+Assignment* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
+ // .generator = %CreateJSGeneratorObject(...);
DCHECK_NOT_NULL(function_state_->generator_object_variable());
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
args->Add(factory()->NewThisFunction(pos), zone());
args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos)
: ThisExpression(kNoSourcePosition),
zone());
- return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
- pos);
+ Expression* allocation =
+ factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, pos);
+ VariableProxy* proxy =
+ factory()->NewVariableProxy(function_state_->generator_object_variable());
+ return factory()->NewAssignment(Token::INIT, proxy, allocation,
+ kNoSourcePosition);
}
Expression* Parser::BuildResolvePromise(Expression* value, int pos) {
@@ -3100,17 +3049,13 @@ Variable* Parser::PromiseVariable() {
}
Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
- Expression* allocation = BuildCreateJSGeneratorObject(pos, kind);
- VariableProxy* init_proxy =
- factory()->NewVariableProxy(function_state_->generator_object_variable());
- Assignment* assignment = factory()->NewAssignment(
- Token::INIT, init_proxy, allocation, kNoSourcePosition);
- VariableProxy* get_proxy =
+ Assignment* assignment = BuildCreateJSGeneratorObject(pos, kind);
+ VariableProxy* generator =
factory()->NewVariableProxy(function_state_->generator_object_variable());
// The position of the yield is important for reporting the exception
// caused by calling the .throw method on a generator suspended at the
// initial yield (i.e. right after generator instantiation).
- return factory()->NewYield(get_proxy, assignment, scope()->start_position(),
+ return factory()->NewYield(generator, assignment, scope()->start_position(),
Yield::kOnExceptionThrow);
}
@@ -3120,12 +3065,14 @@ ZoneList<Statement*>* Parser::ParseFunction(
DeclarationScope* function_scope, int* num_parameters, int* function_length,
bool* has_duplicate_parameters, int* materialized_literal_count,
int* expected_property_count, bool* ok) {
+ ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY);
+
FunctionState function_state(&function_state_, &scope_state_, function_scope);
- DuplicateFinder duplicate_finder(scanner()->unicode_cache());
+ DuplicateFinder duplicate_finder;
ExpressionClassifier formals_classifier(this, &duplicate_finder);
- if (IsGeneratorFunction(kind)) PrepareGeneratorVariables(&function_state);
+ if (IsResumableFunction(kind)) PrepareGeneratorVariables();
ParserFormalParameters formals(function_scope);
ParseFormalParameterList(&formals, CHECK_OK);
@@ -3164,7 +3111,6 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
const AstRawString* function_name, int pos,
const ParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
- ParsingModeScope mode(this, allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY);
ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
static const int kFunctionNameAssignmentIndex = 0;
@@ -3241,7 +3187,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
ParseStatementList(body, Token::RBRACE, CHECK_OK);
}
- if (IsSubclassConstructor(kind)) {
+ if (IsDerivedConstructor(kind)) {
body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition),
kNoSourcePosition),
zone());
@@ -3316,130 +3262,6 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
return result;
}
-Expression* Parser::InstallHomeObject(Expression* function_literal,
- Expression* home_object) {
- Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
- Variable* result_var =
- scope()->NewTemporary(ast_value_factory()->empty_string());
- DoExpression* do_expr =
- factory()->NewDoExpression(do_block, result_var, kNoSourcePosition);
- Assignment* init = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(result_var), function_literal,
- kNoSourcePosition);
- do_block->statements()->Add(
- factory()->NewExpressionStatement(init, kNoSourcePosition), zone());
- Property* home_object_property = factory()->NewProperty(
- factory()->NewVariableProxy(result_var),
- factory()->NewSymbolLiteral("home_object_symbol", kNoSourcePosition),
- kNoSourcePosition);
- Assignment* assignment = factory()->NewAssignment(
- Token::ASSIGN, home_object_property, home_object, kNoSourcePosition);
- do_block->statements()->Add(
- factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
- return do_expr;
-}
-
-const AstRawString* ClassFieldVariableName(bool is_name,
- AstValueFactory* ast_value_factory,
- int index) {
- std::string name =
- ".class-field-" + std::to_string(index) + (is_name ? "-name" : "-func");
- return ast_value_factory->GetOneByteString(name.c_str());
-}
-
-FunctionLiteral* Parser::SynthesizeClassFieldInitializer(int count) {
- DCHECK(count > 0);
- // Makes a function which reads the names and initializers for each class
- // field out of deterministically named local variables and sets each property
- // to the result of evaluating its corresponding initializer in turn.
-
- // This produces a function which looks like
- // function () {
- // this[.class-field-0-name] = .class-field-0-func();
- // this[.class-field-1-name] = .class-field-1-func();
- // [...]
- // this[.class-field-n-name] = .class-field-n-func();
- // return this;
- // }
- // except that it performs defineProperty, so that instead of '=' it has
- // %DefineDataPropertyInLiteral(this, .class-field-0-name,
- // .class-field-0-func(),
- // DONT_ENUM, false)
-
- RaiseLanguageMode(STRICT);
- FunctionKind kind = FunctionKind::kConciseMethod;
- DeclarationScope* initializer_scope = NewFunctionScope(kind);
- SetLanguageMode(initializer_scope, language_mode());
- initializer_scope->set_start_position(scanner()->location().end_pos);
- initializer_scope->set_end_position(scanner()->location().end_pos);
- FunctionState initializer_state(&function_state_, &scope_state_,
- initializer_scope);
- ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(count, zone());
- for (int i = 0; i < count; ++i) {
- const AstRawString* name =
- ClassFieldVariableName(true, ast_value_factory(), i);
- VariableProxy* name_proxy = scope()->NewUnresolved(factory(), name);
- const AstRawString* function_name =
- ClassFieldVariableName(false, ast_value_factory(), i);
- VariableProxy* function_proxy =
- scope()->NewUnresolved(factory(), function_name);
- ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
- args->Add(function_proxy, zone());
- args->Add(ThisExpression(kNoSourcePosition), zone());
- Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args,
- kNoSourcePosition);
- ZoneList<Expression*>* define_property_args =
- new (zone()) ZoneList<Expression*>(5, zone());
- define_property_args->Add(ThisExpression(kNoSourcePosition), zone());
- define_property_args->Add(name_proxy, zone());
- define_property_args->Add(call, zone());
- define_property_args->Add(
- factory()->NewNumberLiteral(DONT_ENUM, kNoSourcePosition), zone());
- define_property_args->Add(
- factory()->NewNumberLiteral(
- false, // TODO(bakkot) function name inference a la class { x =
- // function(){}; static y = function(){}; }
- kNoSourcePosition),
- zone());
- body->Add(factory()->NewExpressionStatement(
- factory()->NewCallRuntime(
- Runtime::kDefineDataProperty,
- define_property_args, // TODO(bakkot) verify that this is
- // the same as object_define_property
- kNoSourcePosition),
- kNoSourcePosition),
- zone());
- }
- body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition),
- kNoSourcePosition),
- zone());
- FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
- ast_value_factory()->empty_string(), initializer_scope, body,
- initializer_state.materialized_literal_count(),
- initializer_state.expected_property_count(), 0, count,
- FunctionLiteral::kNoDuplicateParameters,
- FunctionLiteral::kAnonymousExpression,
- FunctionLiteral::kShouldLazyCompile, initializer_scope->start_position(),
- true);
- function_literal->set_is_class_field_initializer(true);
- return function_literal;
-}
-
-FunctionLiteral* Parser::InsertClassFieldInitializer(
- FunctionLiteral* constructor) {
- Statement* call_initializer = factory()->NewExpressionStatement(
- CallClassFieldInitializer(
- constructor->scope(),
- constructor->scope()->NewUnresolved(
- factory(), ast_value_factory()->this_string(), kNoSourcePosition,
- THIS_VARIABLE)),
- kNoSourcePosition);
- constructor->body()->InsertAt(0, call_initializer, zone());
- return constructor;
-}
-
-// If a class name is specified, this method declares the class variable
-// and sets class_info->proxy to point to that name.
void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope,
ClassInfo* class_info, int class_token_pos,
bool* ok) {
@@ -3459,13 +3281,14 @@ void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope,
// This method declares a property of the given class. It updates the
// following fields of class_info, as appropriate:
// - constructor
-// - static_initializer_var
-// - instance_field_initializers
// - properties
void Parser::DeclareClassProperty(const AstRawString* class_name,
ClassLiteralProperty* property,
+ ClassLiteralProperty::Kind kind,
+ bool is_static, bool is_constructor,
ClassInfo* class_info, bool* ok) {
- if (class_info->has_seen_constructor && class_info->constructor == nullptr) {
+ if (is_constructor) {
+ DCHECK(!class_info->constructor);
class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral();
DCHECK_NOT_NULL(class_info->constructor);
class_info->constructor->set_raw_name(
@@ -3476,47 +3299,7 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
if (property->kind() == ClassLiteralProperty::FIELD) {
DCHECK(allow_harmony_class_fields());
- if (property->is_static()) {
- if (class_info->static_initializer_var == nullptr) {
- class_info->static_initializer_var =
- NewTemporary(ast_value_factory()->empty_string());
- }
- // TODO(bakkot) only do this conditionally
- Expression* function = InstallHomeObject(
- property->value(),
- factory()->NewVariableProxy(class_info->static_initializer_var));
- ZoneList<Expression*>* args =
- new (zone()) ZoneList<Expression*>(2, zone());
- args->Add(function, zone());
- args->Add(factory()->NewVariableProxy(class_info->static_initializer_var),
- zone());
- Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args,
- kNoSourcePosition);
- property->set_value(call);
- } else {
- // if (is_computed_name) { // TODO(bakkot) figure out why this is
- // necessary for non-computed names in full-codegen
- ZoneList<Expression*>* to_name_args =
- new (zone()) ZoneList<Expression*>(1, zone());
- to_name_args->Add(property->key(), zone());
- property->set_key(factory()->NewCallRuntime(
- Runtime::kToName, to_name_args, kNoSourcePosition));
- //}
- const AstRawString* name = ClassFieldVariableName(
- true, ast_value_factory(),
- class_info->instance_field_initializers->length());
- VariableProxy* name_proxy =
- factory()->NewVariableProxy(name, NORMAL_VARIABLE);
- Declaration* name_declaration = factory()->NewVariableDeclaration(
- name_proxy, scope(), kNoSourcePosition);
- Variable* name_var =
- Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST,
- kNeedsInitialization, ok, scope());
- DCHECK(*ok);
- if (!*ok) return;
- class_info->instance_field_initializers->Add(property->value(), zone());
- property->set_value(factory()->NewVariableProxy(name_var));
- }
+ // TODO(littledan): Implement class fields
}
class_info->properties->Add(property, zone());
}
@@ -3526,9 +3309,9 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
// - constructor (if missing, it updates it with a default constructor)
// - proxy
// - extends
-// - static_initializer_var
-// - instance_field_initializers
// - properties
+// - has_name_static_property
+// - has_static_computed_names
Expression* Parser::RewriteClassLiteral(const AstRawString* name,
ClassInfo* class_info, int pos,
bool* ok) {
@@ -3538,22 +3321,12 @@ Expression* Parser::RewriteClassLiteral(const AstRawString* name,
DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
bool has_extends = class_info->extends != nullptr;
- bool has_instance_fields =
- class_info->instance_field_initializers->length() > 0;
- DCHECK(!has_instance_fields || allow_harmony_class_fields());
bool has_default_constructor = class_info->constructor == nullptr;
if (has_default_constructor) {
class_info->constructor =
- DefaultConstructor(name, has_extends, has_instance_fields, pos, end_pos,
- scope()->language_mode());
+ DefaultConstructor(name, has_extends, pos, end_pos);
}
- if (has_instance_fields && !has_extends) {
- class_info->constructor =
- InsertClassFieldInitializer(class_info->constructor);
- class_info->constructor->set_requires_class_field_init(true);
- } // The derived case is handled by rewriting super calls.
-
scope()->set_end_position(end_pos);
if (name != nullptr) {
@@ -3563,12 +3336,9 @@ Expression* Parser::RewriteClassLiteral(const AstRawString* name,
ClassLiteral* class_literal = factory()->NewClassLiteral(
class_info->proxy, class_info->extends, class_info->constructor,
- class_info->properties, pos, end_pos);
-
- if (class_info->static_initializer_var != nullptr) {
- class_literal->set_static_initializer_proxy(
- factory()->NewVariableProxy(class_info->static_initializer_var));
- }
+ class_info->properties, pos, end_pos,
+ class_info->has_name_static_property,
+ class_info->has_static_computed_names);
do_block->statements()->Add(
factory()->NewExpressionStatement(
@@ -3577,53 +3347,6 @@ Expression* Parser::RewriteClassLiteral(const AstRawString* name,
class_literal, kNoSourcePosition),
pos),
zone());
- if (allow_harmony_class_fields() &&
- (has_instance_fields || (has_extends && !has_default_constructor))) {
- // Default constructors for derived classes without fields will not try to
- // read this variable, so there's no need to create it.
- const AstRawString* init_fn_name =
- ast_value_factory()->dot_class_field_init_string();
- Variable* init_fn_var = scope()->DeclareLocal(
- init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE);
- Expression* initializer =
- has_instance_fields
- ? static_cast<Expression*>(SynthesizeClassFieldInitializer(
- class_info->instance_field_initializers->length()))
- : factory()->NewBooleanLiteral(false, kNoSourcePosition);
- Assignment* assignment = factory()->NewAssignment(
- Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer,
- kNoSourcePosition);
- do_block->statements()->Add(
- factory()->NewExpressionStatement(assignment, kNoSourcePosition),
- zone());
- }
- for (int i = 0; i < class_info->instance_field_initializers->length(); ++i) {
- const AstRawString* function_name =
- ClassFieldVariableName(false, ast_value_factory(), i);
- VariableProxy* function_proxy =
- factory()->NewVariableProxy(function_name, NORMAL_VARIABLE);
- Declaration* function_declaration = factory()->NewVariableDeclaration(
- function_proxy, scope(), kNoSourcePosition);
- Variable* function_var =
- Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST,
- kNeedsInitialization, ok, scope());
- if (!*ok) return nullptr;
- Property* prototype_property = factory()->NewProperty(
- factory()->NewVariableProxy(result_var),
- factory()->NewStringLiteral(ast_value_factory()->prototype_string(),
- kNoSourcePosition),
- kNoSourcePosition);
- Expression* function_value = InstallHomeObject(
- class_info->instance_field_initializers->at(i),
- prototype_property); // TODO(bakkot) ideally this would be conditional,
- // especially in trivial cases
- Assignment* function_assignment = factory()->NewAssignment(
- Token::INIT, factory()->NewVariableProxy(function_var), function_value,
- kNoSourcePosition);
- do_block->statements()->Add(factory()->NewExpressionStatement(
- function_assignment, kNoSourcePosition),
- zone());
- }
do_block->set_scope(scope()->FinalizeBlockScope());
do_expr->set_represented_function(class_info->constructor);
AddFunctionForNameInference(class_info->constructor);
@@ -3775,47 +3498,10 @@ void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE) {
// Copy over the counters from the background thread to the main counters on
// the isolate.
- // TODO(cbruni,lpy): properly attach the runtime stats to the trace for
- // background parsing.
isolate->counters()->runtime_call_stats()->Add(runtime_call_stats_);
}
}
-
-// ----------------------------------------------------------------------------
-// The Parser interface.
-
-
-bool Parser::ParseStatic(ParseInfo* info) {
- Parser parser(info);
- if (parser.Parse(info)) {
- info->set_language_mode(info->literal()->language_mode());
- return true;
- }
- return false;
-}
-
-
-bool Parser::Parse(ParseInfo* info) {
- DCHECK(info->literal() == NULL);
- FunctionLiteral* result = NULL;
- // Ok to use Isolate here; this function is only called in the main thread.
- DCHECK(parsing_on_main_thread_);
- Isolate* isolate = info->isolate();
-
- if (info->is_toplevel()) {
- SetCachedData(info);
- result = ParseProgram(isolate, info);
- } else {
- result = ParseFunction(isolate, info);
- }
- info->set_literal(result);
-
- Internalize(isolate, info->script(), result == NULL);
- return (result != NULL);
-}
-
-
void Parser::ParseOnBackground(ParseInfo* info) {
parsing_on_main_thread_ = false;
@@ -3823,7 +3509,13 @@ void Parser::ParseOnBackground(ParseInfo* info) {
FunctionLiteral* result = NULL;
ParserLogger logger;
- if (produce_cached_parse_data()) log_ = &logger;
+ if (produce_cached_parse_data()) {
+ if (allow_lazy_) {
+ log_ = &logger;
+ } else {
+ compile_options_ = ScriptCompiler::kNoCompileOptions;
+ }
+ }
if (FLAG_runtime_stats) {
// Create separate runtime stats for background parsing.
runtime_call_stats_ = new (zone()) RuntimeCallStats();
@@ -3837,7 +3529,8 @@ void Parser::ParseOnBackground(ParseInfo* info) {
} else {
DCHECK(info->character_stream() == nullptr);
stream.reset(ScannerStream::For(info->source_stream(),
- info->source_stream_encoding()));
+ info->source_stream_encoding(),
+ runtime_call_stats_));
stream_ptr = stream.get();
}
DCHECK(info->maybe_outer_scope_info().is_null());
@@ -3867,9 +3560,13 @@ void Parser::ParseOnBackground(ParseInfo* info) {
if (result != NULL) *info->cached_data() = logger.GetScriptData();
log_ = NULL;
}
- if (FLAG_runtime_stats) {
- // TODO(cbruni,lpy): properly attach the runtime stats to the trace for
- // background parsing.
+ if (FLAG_runtime_stats &
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) {
+ auto value = v8::tracing::TracedValue::Create();
+ runtime_call_stats_->Dump(value.get());
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats"),
+ "V8.RuntimeStats", TRACE_EVENT_SCOPE_THREAD,
+ "runtime-call-stats", std::move(value));
}
}
@@ -4057,6 +3754,23 @@ Expression* Parser::SpreadCall(Expression* function,
// Super calls
// $super_constructor = %_GetSuperConstructor(<this-function>)
// %reflect_construct($super_constructor, args, new.target)
+
+ bool only_last_arg_is_spread = false;
+ for (int i = 0; i < args->length(); i++) {
+ if (args->at(i)->IsSpread()) {
+ if (i == args->length() - 1) {
+ only_last_arg_is_spread = true;
+ }
+ break;
+ }
+ }
+
+ if (only_last_arg_is_spread) {
+ // Handle in BytecodeGenerator.
+ Expression* super_call_ref = NewSuperCallReference(pos);
+ return factory()->NewCall(super_call_ref, args, pos);
+ }
+ args = PrepareSpreadArguments(args);
ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
Expression* super_constructor = factory()->NewCallRuntime(
@@ -4066,6 +3780,7 @@ Expression* Parser::SpreadCall(Expression* function,
return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
pos);
} else {
+ args = PrepareSpreadArguments(args);
if (function->IsProperty()) {
// Method calls
if (function->AsProperty()->IsSuperAccess()) {
@@ -4096,6 +3811,7 @@ Expression* Parser::SpreadCall(Expression* function,
Expression* Parser::SpreadCallNew(Expression* function,
ZoneList<Expression*>* args, int pos) {
+ args = PrepareSpreadArguments(args);
args->InsertAt(0, function, zone());
return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
@@ -4143,23 +3859,13 @@ Expression* Parser::ExpressionListToExpression(ZoneList<Expression*>* args) {
// when desugaring the body of async_function.
void Parser::PrepareAsyncFunctionBody(ZoneList<Statement*>* body,
FunctionKind kind, int pos) {
- // function async_function() {
- // .generator_object = %CreateGeneratorObject();
- // BuildRejectPromiseOnException({
- // ... block ...
- // return %ResolvePromise(.promise, expr), .promise;
- // })
- // }
-
- Variable* temp =
- NewTemporary(ast_value_factory()->dot_generator_object_string());
- function_state_->set_generator_object_variable(temp);
-
- Expression* init_generator_variable = factory()->NewAssignment(
- Token::INIT, factory()->NewVariableProxy(temp),
- BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition);
- body->Add(factory()->NewExpressionStatement(init_generator_variable,
- kNoSourcePosition),
+ // When parsing an async arrow function, we get here without having called
+ // PrepareGeneratorVariables yet, so do it now.
+ if (function_state_->generator_object_variable() == nullptr) {
+ PrepareGeneratorVariables();
+ }
+ body->Add(factory()->NewExpressionStatement(
+ BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition),
zone());
}
@@ -4167,7 +3873,7 @@ void Parser::PrepareAsyncFunctionBody(ZoneList<Statement*>* body,
void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block,
Expression* return_value, bool* ok) {
// function async_function() {
- // .generator_object = %CreateGeneratorObject();
+ // .generator_object = %CreateJSGeneratorObject();
// BuildRejectPromiseOnException({
// ... block ...
// return %ResolvePromise(.promise, expr), .promise;
@@ -4204,10 +3910,7 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
// TODO(littledan): investigate why this ordering is needed in more detail.
Variable* generator_object_variable =
function_state_->generator_object_variable();
-
- // If generator_object_variable is null,
- // TODO(littledan): Is this necessary?
- if (!generator_object_variable) return value;
+ DCHECK_NOT_NULL(generator_object_variable);
const int nopos = kNoSourcePosition;
@@ -4539,8 +4242,7 @@ void Parser::SetFunctionName(Expression* value, const AstRawString* name) {
// let mode = kNext;
// let output = undefined;
//
-// let iterator = iterable[Symbol.iterator]();
-// if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
+// let iterator = GetIterator(iterable);
//
// while (true) {
// // From the generator to the iterator:
@@ -4643,41 +4345,17 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
initialize_output = factory()->NewExpressionStatement(assignment, nopos);
}
- // let iterator = iterable[Symbol.iterator];
+ // let iterator = GetIterator(iterable);
Variable* var_iterator = NewTemporary(ast_value_factory()->empty_string());
Statement* get_iterator;
{
- Expression* iterator = GetIterator(iterable, nopos);
+ Expression* iterator = factory()->NewGetIterator(iterable, nopos);
Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator);
Expression* assignment = factory()->NewAssignment(
Token::ASSIGN, iterator_proxy, iterator, nopos);
get_iterator = factory()->NewExpressionStatement(assignment, nopos);
}
- // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
- Statement* validate_iterator;
- {
- Expression* is_receiver_call;
- {
- auto args = new (zone()) ZoneList<Expression*>(1, zone());
- args->Add(factory()->NewVariableProxy(var_iterator), zone());
- is_receiver_call =
- factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
- }
-
- Statement* throw_call;
- {
- Expression* call =
- NewThrowTypeError(MessageTemplate::kSymbolIteratorInvalid,
- ast_value_factory()->empty_string(), nopos);
- throw_call = factory()->NewExpressionStatement(call, nopos);
- }
-
- validate_iterator = factory()->NewIfStatement(
- is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
- nopos);
- }
-
// output = iterator.next(input);
Statement* call_next;
{
@@ -4910,8 +4588,7 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
Scope* catch_scope = NewScope(CATCH_SCOPE);
catch_scope->set_is_hidden();
const AstRawString* name = ast_value_factory()->dot_catch_string();
- Variable* catch_variable = catch_scope->DeclareLocal(
- name, VAR, kCreatedInitialized, NORMAL_VARIABLE);
+ Variable* catch_variable = catch_scope->DeclareLocal(name, VAR);
try_catch = factory()->NewTryCatchStatementForDesugaring(
try_block, catch_scope, catch_variable, catch_block, nopos);
@@ -4982,12 +4659,11 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
// 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, 7, true, nopos);
+ 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(validate_iterator, zone());
do_block_->statements()->Add(loop, zone());
do_block_->statements()->Add(maybe_return_value, zone());
@@ -5198,8 +4874,7 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
{
Scope* catch_scope = NewScopeWithParent(use_scope, CATCH_SCOPE);
Variable* catch_variable =
- catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
- kCreatedInitialized, NORMAL_VARIABLE);
+ catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
catch_scope->set_is_hidden();
Statement* rethrow;
@@ -5305,8 +4980,7 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope,
Scope* catch_scope = NewScopeWithParent(scope, CATCH_SCOPE);
Variable* catch_variable =
- catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
- kCreatedInitialized, NORMAL_VARIABLE);
+ catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
catch_scope->set_is_hidden();
try_call_return = factory()->NewTryCatchStatement(
@@ -5410,7 +5084,7 @@ Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
// %ReThrow(e);
// }
// } finally {
- // if (!(completion === kNormalCompletion || IS_UNDEFINED(#iterator))) {
+ // if (!(completion === kNormalCompletion)) {
// #BuildIteratorCloseForCompletion(#iterator, completion)
// }
// }
@@ -5421,18 +5095,13 @@ Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
const int nopos = kNoSourcePosition;
- // !(completion === kNormalCompletion || IS_UNDEFINED(#iterator))
+ // !(completion === kNormalCompletion)
Expression* closing_condition;
{
- Expression* lhs = factory()->NewCompareOperation(
+ Expression* cmp = factory()->NewCompareOperation(
Token::EQ_STRICT, factory()->NewVariableProxy(var_completion),
factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
- Expression* rhs = factory()->NewCompareOperation(
- Token::EQ_STRICT, factory()->NewVariableProxy(loop->iterator()),
- factory()->NewUndefinedLiteral(nopos), nopos);
- closing_condition = factory()->NewUnaryOperation(
- Token::NOT, factory()->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
- nopos);
+ closing_condition = factory()->NewUnaryOperation(Token::NOT, cmp, nopos);
}
Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos);