Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/parsing/rewriter.cc

Issue 2167713004: Always finalize blocks after parsing, also for do-expressions (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/rewriter.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/parsing/rewriter.h" 5 #include "src/parsing/rewriter.h"
6 6
7 #include "src/ast/ast.h" 7 #include "src/ast/ast.h"
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/parsing/parser.h" 9 #include "src/parsing/parser.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 13
14 class Processor final : public AstVisitor<Processor> { 14 class Processor final : public AstVisitor<Processor> {
15 public: 15 public:
16 Processor(Isolate* isolate, Scope* scope, Variable* result, 16 Processor(Isolate* isolate, Scope* closure_scope, Variable* result,
17 AstValueFactory* ast_value_factory) 17 AstValueFactory* ast_value_factory)
18 : result_(result), 18 : result_(result),
19 result_assigned_(false), 19 result_assigned_(false),
20 replacement_(nullptr), 20 replacement_(nullptr),
21 is_set_(false), 21 is_set_(false),
22 zone_(ast_value_factory->zone()), 22 zone_(ast_value_factory->zone()),
23 scope_(scope), 23 closure_scope_(closure_scope),
24 factory_(ast_value_factory) { 24 factory_(ast_value_factory) {
25 DCHECK_EQ(closure_scope, closure_scope->ClosureScope());
25 InitializeAstVisitor(isolate); 26 InitializeAstVisitor(isolate);
26 } 27 }
27 28
28 Processor(Parser* parser, Scope* scope, Variable* result, 29 Processor(Parser* parser, Scope* closure_scope, Variable* result,
29 AstValueFactory* ast_value_factory) 30 AstValueFactory* ast_value_factory)
30 : result_(result), 31 : result_(result),
31 result_assigned_(false), 32 result_assigned_(false),
32 replacement_(nullptr), 33 replacement_(nullptr),
33 is_set_(false), 34 is_set_(false),
34 zone_(ast_value_factory->zone()), 35 zone_(ast_value_factory->zone()),
35 scope_(scope), 36 closure_scope_(closure_scope),
36 factory_(ast_value_factory) { 37 factory_(ast_value_factory) {
38 DCHECK_EQ(closure_scope, closure_scope->ClosureScope());
37 InitializeAstVisitor(parser->stack_limit()); 39 InitializeAstVisitor(parser->stack_limit());
38 } 40 }
39 41
40 void Process(ZoneList<Statement*>* statements); 42 void Process(ZoneList<Statement*>* statements);
41 bool result_assigned() const { return result_assigned_; } 43 bool result_assigned() const { return result_assigned_; }
42 44
43 Zone* zone() { return zone_; } 45 Zone* zone() { return zone_; }
44 Scope* scope() { return scope_; } 46 Scope* closure_scope() { return closure_scope_; }
45 AstNodeFactory* factory() { return &factory_; } 47 AstNodeFactory* factory() { return &factory_; }
46 48
47 // Returns ".result = value" 49 // Returns ".result = value"
48 Expression* SetResult(Expression* value) { 50 Expression* SetResult(Expression* value) {
49 result_assigned_ = true; 51 result_assigned_ = true;
50 VariableProxy* result_proxy = factory()->NewVariableProxy(result_); 52 VariableProxy* result_proxy = factory()->NewVariableProxy(result_);
51 return factory()->NewAssignment(Token::ASSIGN, result_proxy, value, 53 return factory()->NewAssignment(Token::ASSIGN, result_proxy, value,
52 kNoSourcePosition); 54 kNoSourcePosition);
53 } 55 }
54 56
(...skipping 13 matching lines...) Expand all
68 // [replacement_]. In many cases this will just be the original node. 70 // [replacement_]. In many cases this will just be the original node.
69 Statement* replacement_; 71 Statement* replacement_;
70 72
71 // To avoid storing to .result all the time, we eliminate some of 73 // To avoid storing to .result all the time, we eliminate some of
72 // the stores by keeping track of whether or not we're sure .result 74 // the stores by keeping track of whether or not we're sure .result
73 // will be overwritten anyway. This is a bit more tricky than what I 75 // will be overwritten anyway. This is a bit more tricky than what I
74 // was hoping for. 76 // was hoping for.
75 bool is_set_; 77 bool is_set_;
76 78
77 Zone* zone_; 79 Zone* zone_;
78 Scope* scope_; 80 Scope* closure_scope_;
79 AstNodeFactory factory_; 81 AstNodeFactory factory_;
80 82
81 // Node visitors. 83 // Node visitors.
82 #define DEF_VISIT(type) void Visit##type(type* node); 84 #define DEF_VISIT(type) void Visit##type(type* node);
83 AST_NODE_LIST(DEF_VISIT) 85 AST_NODE_LIST(DEF_VISIT)
84 #undef DEF_VISIT 86 #undef DEF_VISIT
85 87
86 void VisitIterationStatement(IterationStatement* stmt); 88 void VisitIterationStatement(IterationStatement* stmt);
87 89
88 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 90 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { 218 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
217 // Rewrite both try and finally block (in reverse order). 219 // Rewrite both try and finally block (in reverse order).
218 bool set_after = is_set_; 220 bool set_after = is_set_;
219 is_set_ = true; // Don't normally need to assign in finally block. 221 is_set_ = true; // Don't normally need to assign in finally block.
220 Visit(node->finally_block()); 222 Visit(node->finally_block());
221 node->set_finally_block(replacement_->AsBlock()); 223 node->set_finally_block(replacement_->AsBlock());
222 { // Save .result value at the beginning of the finally block and restore it 224 { // Save .result value at the beginning of the finally block and restore it
223 // at the end again: ".backup = .result; ...; .result = .backup" 225 // at the end again: ".backup = .result; ...; .result = .backup"
224 // This is necessary because the finally block does not normally contribute 226 // This is necessary because the finally block does not normally contribute
225 // to the completion value. 227 // to the completion value.
226 CHECK(scope() != nullptr); 228 CHECK_NOT_NULL(closure_scope());
227 Variable* backup = scope()->NewTemporary( 229 Variable* backup = closure_scope()->NewTemporary(
228 factory()->ast_value_factory()->dot_result_string()); 230 factory()->ast_value_factory()->dot_result_string());
229 Expression* backup_proxy = factory()->NewVariableProxy(backup); 231 Expression* backup_proxy = factory()->NewVariableProxy(backup);
230 Expression* result_proxy = factory()->NewVariableProxy(result_); 232 Expression* result_proxy = factory()->NewVariableProxy(result_);
231 Expression* save = factory()->NewAssignment( 233 Expression* save = factory()->NewAssignment(
232 Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition); 234 Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition);
233 Expression* restore = factory()->NewAssignment( 235 Expression* restore = factory()->NewAssignment(
234 Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition); 236 Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition);
235 node->finally_block()->statements()->InsertAt( 237 node->finally_block()->statements()->InsertAt(
236 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone()); 238 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone());
237 node->finally_block()->statements()->Add( 239 node->finally_block()->statements()->Add(
238 factory()->NewExpressionStatement(restore, kNoSourcePosition), zone()); 240 factory()->NewExpressionStatement(restore, kNoSourcePosition), zone());
239 } 241 }
240 is_set_ = set_after; 242 is_set_ = set_after;
241 Visit(node->try_block()); 243 Visit(node->try_block());
242 node->set_try_block(replacement_->AsBlock()); 244 node->set_try_block(replacement_->AsBlock());
243 replacement_ = node; 245 replacement_ = node;
244 246
245 if (!is_set_) { 247 if (!is_set_) {
246 is_set_ = true; 248 is_set_ = true;
247 replacement_ = AssignUndefinedBefore(node); 249 replacement_ = AssignUndefinedBefore(node);
248 } 250 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 #define DEF_VISIT(type) \ 328 #define DEF_VISIT(type) \
327 void Processor::Visit##type(type* expr) { UNREACHABLE(); } 329 void Processor::Visit##type(type* expr) { UNREACHABLE(); }
328 DECLARATION_NODE_LIST(DEF_VISIT) 330 DECLARATION_NODE_LIST(DEF_VISIT)
329 #undef DEF_VISIT 331 #undef DEF_VISIT
330 332
331 333
332 // Assumes code has been parsed. Mutates the AST, so the AST should not 334 // Assumes code has been parsed. Mutates the AST, so the AST should not
333 // continue to be used in the case of failure. 335 // continue to be used in the case of failure.
334 bool Rewriter::Rewrite(ParseInfo* info) { 336 bool Rewriter::Rewrite(ParseInfo* info) {
335 FunctionLiteral* function = info->literal(); 337 FunctionLiteral* function = info->literal();
336 DCHECK(function != NULL); 338 DCHECK_NOT_NULL(function);
337 Scope* scope = function->scope(); 339 Scope* scope = function->scope();
338 DCHECK(scope != NULL); 340 DCHECK_NOT_NULL(scope);
339 if (!scope->is_script_scope() && !scope->is_eval_scope()) return true; 341 if (!scope->is_script_scope() && !scope->is_eval_scope()) return true;
342 Scope* closure_scope = scope->ClosureScope();
340 343
341 ZoneList<Statement*>* body = function->body(); 344 ZoneList<Statement*>* body = function->body();
342 if (!body->is_empty()) { 345 if (!body->is_empty()) {
343 Variable* result = 346 Variable* result = closure_scope->NewTemporary(
344 scope->NewTemporary(info->ast_value_factory()->dot_result_string()); 347 info->ast_value_factory()->dot_result_string());
345 // The name string must be internalized at this point. 348 // The name string must be internalized at this point.
346 DCHECK(!result->name().is_null()); 349 DCHECK(!result->name().is_null());
347 Processor processor(info->isolate(), scope, result, 350 Processor processor(info->isolate(), closure_scope, result,
348 info->ast_value_factory()); 351 info->ast_value_factory());
349 processor.Process(body); 352 processor.Process(body);
350 if (processor.HasStackOverflow()) return false; 353 if (processor.HasStackOverflow()) return false;
351 354
352 if (processor.result_assigned()) { 355 if (processor.result_assigned()) {
353 int pos = kNoSourcePosition; 356 int pos = kNoSourcePosition;
354 VariableProxy* result_proxy = 357 VariableProxy* result_proxy =
355 processor.factory()->NewVariableProxy(result, pos); 358 processor.factory()->NewVariableProxy(result, pos);
356 Statement* result_statement = 359 Statement* result_statement =
357 processor.factory()->NewReturnStatement(result_proxy, pos); 360 processor.factory()->NewReturnStatement(result_proxy, pos);
358 body->Add(result_statement, info->zone()); 361 body->Add(result_statement, info->zone());
359 } 362 }
360 } 363 }
361 364
362 return true; 365 return true;
363 } 366 }
364 367
365 368 bool Rewriter::Rewrite(Parser* parser, Scope* closure_scope, DoExpression* expr,
366 bool Rewriter::Rewrite(Parser* parser, DoExpression* expr,
367 AstValueFactory* factory) { 369 AstValueFactory* factory) {
368 Block* block = expr->block(); 370 Block* block = expr->block();
369 Scope* scope = block->scope(); 371 DCHECK_EQ(closure_scope, closure_scope->ClosureScope());
372 DCHECK(block->scope() == nullptr ||
373 block->scope()->ClosureScope() == closure_scope);
370 ZoneList<Statement*>* body = block->statements(); 374 ZoneList<Statement*>* body = block->statements();
371 VariableProxy* result = expr->result(); 375 VariableProxy* result = expr->result();
372 Variable* result_var = result->var(); 376 Variable* result_var = result->var();
373 377
374 if (!body->is_empty()) { 378 if (!body->is_empty()) {
375 Processor processor(parser, scope, result_var, factory); 379 Processor processor(parser, closure_scope, result_var, factory);
376 processor.Process(body); 380 processor.Process(body);
377 if (processor.HasStackOverflow()) return false; 381 if (processor.HasStackOverflow()) return false;
378 382
379 if (!processor.result_assigned()) { 383 if (!processor.result_assigned()) {
380 AstNodeFactory* node_factory = processor.factory(); 384 AstNodeFactory* node_factory = processor.factory();
381 Expression* undef = node_factory->NewUndefinedLiteral(kNoSourcePosition); 385 Expression* undef = node_factory->NewUndefinedLiteral(kNoSourcePosition);
382 Statement* completion = node_factory->NewExpressionStatement( 386 Statement* completion = node_factory->NewExpressionStatement(
383 processor.SetResult(undef), expr->position()); 387 processor.SetResult(undef), expr->position());
384 body->Add(completion, factory->zone()); 388 body->Add(completion, factory->zone());
385 } 389 }
386 } 390 }
387 return true; 391 return true;
388 } 392 }
389 393
390 394
391 } // namespace internal 395 } // namespace internal
392 } // namespace v8 396 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/rewriter.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698