Commit f02018ce authored by verwaest's avatar verwaest Committed by Commit bot

Always finalize blocks after parsing, also for do-expressions

Rather than finalizing after rewriting do-expressions, we rewrite in the
outer scope if the block scope was finalized. Rewriting do expressions
cannot introduce any new nodes that requires the block to stay around,
so finalizing before and after is equivalent. (Only a temporary is
introduced which always ends up in a ClosureScope)

BUG=v8:5209
R=rossberg@chromium.org, caitpotter88@gmail.com, adamk@chromium.org

Review-Url: https://codereview.chromium.org/2167713004
Cr-Commit-Position: refs/heads/master@{#38193}
parent 35a195e1
...@@ -2291,9 +2291,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, ...@@ -2291,9 +2291,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
return assignment_statement; return assignment_statement;
} }
Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels,
bool finalize_block_scope, bool* ok) {
// The harmony mode uses block elements instead of statements. // The harmony mode uses block elements instead of statements.
// //
// Block :: // Block ::
...@@ -2319,19 +2317,12 @@ Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, ...@@ -2319,19 +2317,12 @@ Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels,
} }
Expect(Token::RBRACE, CHECK_OK); Expect(Token::RBRACE, CHECK_OK);
block_scope->set_end_position(scanner()->location().end_pos); block_scope->set_end_position(scanner()->location().end_pos);
if (finalize_block_scope) {
block_scope = block_scope->FinalizeBlockScope(); block_scope = block_scope->FinalizeBlockScope();
}
body->set_scope(block_scope); body->set_scope(block_scope);
return body; return body;
} }
Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
return ParseBlock(labels, true, ok);
}
Block* Parser::DeclarationParsingResult::BuildInitializationBlock( Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
ZoneList<const AstRawString*>* names, bool* ok) { ZoneList<const AstRawString*>* names, bool* ok) {
Block* result = descriptor.parser->factory()->NewBlock( Block* result = descriptor.parser->factory()->NewBlock(
...@@ -4221,13 +4212,13 @@ DoExpression* Parser::ParseDoExpression(bool* ok) { ...@@ -4221,13 +4212,13 @@ DoExpression* Parser::ParseDoExpression(bool* ok) {
Expect(Token::DO, CHECK_OK); Expect(Token::DO, CHECK_OK);
Variable* result = Variable* result =
scope()->NewTemporary(ast_value_factory()->dot_result_string()); scope()->NewTemporary(ast_value_factory()->dot_result_string());
Block* block = ParseBlock(nullptr, false, CHECK_OK); Block* block = ParseBlock(nullptr, CHECK_OK);
DoExpression* expr = factory()->NewDoExpression(block, result, pos); DoExpression* expr = factory()->NewDoExpression(block, result, pos);
if (!Rewriter::Rewrite(this, expr, ast_value_factory())) { if (!Rewriter::Rewrite(this, scope()->ClosureScope(), expr,
ast_value_factory())) {
*ok = false; *ok = false;
return nullptr; return nullptr;
} }
block->set_scope(block->scope()->FinalizeBlockScope());
return expr; return expr;
} }
...@@ -5105,7 +5096,7 @@ Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier, ...@@ -5105,7 +5096,7 @@ Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
int end_pos = scanner()->location().end_pos; int end_pos = scanner()->location().end_pos;
if (constructor == NULL) { if (constructor == NULL) {
DCHECK_EQ(this->scope(), block_scope); DCHECK_EQ(scope(), block_scope);
constructor = DefaultConstructor(name, has_extends, pos, end_pos, constructor = DefaultConstructor(name, has_extends, pos, end_pos,
block_scope->language_mode()); block_scope->language_mode());
} }
...@@ -5131,7 +5122,8 @@ Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier, ...@@ -5131,7 +5122,8 @@ Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
do_block->statements()->Add( do_block->statements()->Add(
factory()->NewExpressionStatement(class_literal, pos), zone()); factory()->NewExpressionStatement(class_literal, pos), zone());
do_expr->set_represented_function(constructor); do_expr->set_represented_function(constructor);
Rewriter::Rewrite(this, do_expr, ast_value_factory()); Rewriter::Rewrite(this, scope()->ClosureScope(), do_expr,
ast_value_factory());
return do_expr; return do_expr;
} }
...@@ -6640,7 +6632,7 @@ Expression* ParserTraits::RewriteYieldStar( ...@@ -6640,7 +6632,7 @@ Expression* ParserTraits::RewriteYieldStar(
Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
yield_star = factory->NewDoExpression(do_block, dot_result, nopos); yield_star = factory->NewDoExpression(do_block, dot_result, nopos);
Rewriter::Rewrite(parser_, yield_star, avfactory); Rewriter::Rewrite(parser_, scope->ClosureScope(), yield_star, avfactory);
} }
return yield_star; return yield_star;
......
...@@ -813,8 +813,6 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -813,8 +813,6 @@ class Parser : public ParserBase<ParserTraits> {
bool default_export, bool* ok); bool default_export, bool* ok);
Statement* ParseNativeDeclaration(bool* ok); Statement* ParseNativeDeclaration(bool* ok);
Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok); Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
Block* ParseBlock(ZoneList<const AstRawString*>* labels,
bool finalize_block_scope, bool* ok);
Block* ParseVariableStatement(VariableDeclarationContext var_context, Block* ParseVariableStatement(VariableDeclarationContext var_context,
ZoneList<const AstRawString*>* names, ZoneList<const AstRawString*>* names,
bool* ok); bool* ok);
......
...@@ -13,27 +13,29 @@ namespace internal { ...@@ -13,27 +13,29 @@ namespace internal {
class Processor final : public AstVisitor<Processor> { class Processor final : public AstVisitor<Processor> {
public: public:
Processor(Isolate* isolate, Scope* scope, Variable* result, Processor(Isolate* isolate, Scope* closure_scope, Variable* result,
AstValueFactory* ast_value_factory) AstValueFactory* ast_value_factory)
: result_(result), : result_(result),
result_assigned_(false), result_assigned_(false),
replacement_(nullptr), replacement_(nullptr),
is_set_(false), is_set_(false),
zone_(ast_value_factory->zone()), zone_(ast_value_factory->zone()),
scope_(scope), closure_scope_(closure_scope),
factory_(ast_value_factory) { factory_(ast_value_factory) {
DCHECK_EQ(closure_scope, closure_scope->ClosureScope());
InitializeAstVisitor(isolate); InitializeAstVisitor(isolate);
} }
Processor(Parser* parser, Scope* scope, Variable* result, Processor(Parser* parser, Scope* closure_scope, Variable* result,
AstValueFactory* ast_value_factory) AstValueFactory* ast_value_factory)
: result_(result), : result_(result),
result_assigned_(false), result_assigned_(false),
replacement_(nullptr), replacement_(nullptr),
is_set_(false), is_set_(false),
zone_(ast_value_factory->zone()), zone_(ast_value_factory->zone()),
scope_(scope), closure_scope_(closure_scope),
factory_(ast_value_factory) { factory_(ast_value_factory) {
DCHECK_EQ(closure_scope, closure_scope->ClosureScope());
InitializeAstVisitor(parser->stack_limit()); InitializeAstVisitor(parser->stack_limit());
} }
...@@ -41,7 +43,7 @@ class Processor final : public AstVisitor<Processor> { ...@@ -41,7 +43,7 @@ class Processor final : public AstVisitor<Processor> {
bool result_assigned() const { return result_assigned_; } bool result_assigned() const { return result_assigned_; }
Zone* zone() { return zone_; } Zone* zone() { return zone_; }
Scope* scope() { return scope_; } Scope* closure_scope() { return closure_scope_; }
AstNodeFactory* factory() { return &factory_; } AstNodeFactory* factory() { return &factory_; }
// Returns ".result = value" // Returns ".result = value"
...@@ -75,7 +77,7 @@ class Processor final : public AstVisitor<Processor> { ...@@ -75,7 +77,7 @@ class Processor final : public AstVisitor<Processor> {
bool is_set_; bool is_set_;
Zone* zone_; Zone* zone_;
Scope* scope_; Scope* closure_scope_;
AstNodeFactory factory_; AstNodeFactory factory_;
// Node visitors. // Node visitors.
...@@ -223,8 +225,8 @@ void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { ...@@ -223,8 +225,8 @@ void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
// at the end again: ".backup = .result; ...; .result = .backup" // at the end again: ".backup = .result; ...; .result = .backup"
// This is necessary because the finally block does not normally contribute // This is necessary because the finally block does not normally contribute
// to the completion value. // to the completion value.
CHECK(scope() != nullptr); CHECK_NOT_NULL(closure_scope());
Variable* backup = scope()->NewTemporary( Variable* backup = closure_scope()->NewTemporary(
factory()->ast_value_factory()->dot_result_string()); factory()->ast_value_factory()->dot_result_string());
Expression* backup_proxy = factory()->NewVariableProxy(backup); Expression* backup_proxy = factory()->NewVariableProxy(backup);
Expression* result_proxy = factory()->NewVariableProxy(result_); Expression* result_proxy = factory()->NewVariableProxy(result_);
...@@ -333,18 +335,19 @@ DECLARATION_NODE_LIST(DEF_VISIT) ...@@ -333,18 +335,19 @@ DECLARATION_NODE_LIST(DEF_VISIT)
// continue to be used in the case of failure. // continue to be used in the case of failure.
bool Rewriter::Rewrite(ParseInfo* info) { bool Rewriter::Rewrite(ParseInfo* info) {
FunctionLiteral* function = info->literal(); FunctionLiteral* function = info->literal();
DCHECK(function != NULL); DCHECK_NOT_NULL(function);
Scope* scope = function->scope(); Scope* scope = function->scope();
DCHECK(scope != NULL); DCHECK_NOT_NULL(scope);
if (!scope->is_script_scope() && !scope->is_eval_scope()) return true; if (!scope->is_script_scope() && !scope->is_eval_scope()) return true;
Scope* closure_scope = scope->ClosureScope();
ZoneList<Statement*>* body = function->body(); ZoneList<Statement*>* body = function->body();
if (!body->is_empty()) { if (!body->is_empty()) {
Variable* result = Variable* result = closure_scope->NewTemporary(
scope->NewTemporary(info->ast_value_factory()->dot_result_string()); info->ast_value_factory()->dot_result_string());
// The name string must be internalized at this point. // The name string must be internalized at this point.
DCHECK(!result->name().is_null()); DCHECK(!result->name().is_null());
Processor processor(info->isolate(), scope, result, Processor processor(info->isolate(), closure_scope, result,
info->ast_value_factory()); info->ast_value_factory());
processor.Process(body); processor.Process(body);
if (processor.HasStackOverflow()) return false; if (processor.HasStackOverflow()) return false;
...@@ -362,17 +365,18 @@ bool Rewriter::Rewrite(ParseInfo* info) { ...@@ -362,17 +365,18 @@ bool Rewriter::Rewrite(ParseInfo* info) {
return true; return true;
} }
bool Rewriter::Rewrite(Parser* parser, Scope* closure_scope, DoExpression* expr,
bool Rewriter::Rewrite(Parser* parser, DoExpression* expr,
AstValueFactory* factory) { AstValueFactory* factory) {
Block* block = expr->block(); Block* block = expr->block();
Scope* scope = block->scope(); DCHECK_EQ(closure_scope, closure_scope->ClosureScope());
DCHECK(block->scope() == nullptr ||
block->scope()->ClosureScope() == closure_scope);
ZoneList<Statement*>* body = block->statements(); ZoneList<Statement*>* body = block->statements();
VariableProxy* result = expr->result(); VariableProxy* result = expr->result();
Variable* result_var = result->var(); Variable* result_var = result->var();
if (!body->is_empty()) { if (!body->is_empty()) {
Processor processor(parser, scope, result_var, factory); Processor processor(parser, closure_scope, result_var, factory);
processor.Process(body); processor.Process(body);
if (processor.HasStackOverflow()) return false; if (processor.HasStackOverflow()) return false;
......
...@@ -12,6 +12,7 @@ class AstValueFactory; ...@@ -12,6 +12,7 @@ class AstValueFactory;
class DoExpression; class DoExpression;
class ParseInfo; class ParseInfo;
class Parser; class Parser;
class Scope;
class Rewriter { class Rewriter {
public: public:
...@@ -24,8 +25,12 @@ class Rewriter { ...@@ -24,8 +25,12 @@ class Rewriter {
static bool Rewrite(ParseInfo* info); static bool Rewrite(ParseInfo* info);
// Rewrite a list of statements, using the same rules as a top-level program, // Rewrite a list of statements, using the same rules as a top-level program,
// to ensure identical behaviour of completion result. // to ensure identical behaviour of completion result. The temporary is added
static bool Rewrite(Parser* parser, DoExpression* expr, // to the closure scope of the do-expression, which matches the closure scope
// of the outer scope (the do-expression itself runs in a block scope, not a
// closure scope). This closure scope needs to be passed in since the
// do-expression could have dropped its own block scope.
static bool Rewrite(Parser* parser, Scope* closure_scope, DoExpression* expr,
AstValueFactory* factory); AstValueFactory* factory);
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment