5 #include "src/parsing/rewriter.h" 7 #include "src/ast/ast.h" 8 #include "src/ast/scopes.h" 9 #include "src/objects-inl.h" 10 #include "src/parsing/parse-info.h" 11 #include "src/parsing/parser.h" 21 replacement_(
nullptr),
22 zone_(ast_value_factory->zone()),
23 closure_scope_(closure_scope),
24 factory_(ast_value_factory, ast_value_factory->zone()),
25 result_assigned_(
false),
28 DCHECK_EQ(closure_scope, closure_scope->GetClosureScope());
29 InitializeAstVisitor(stack_limit);
35 replacement_(
nullptr),
36 zone_(ast_value_factory->zone()),
37 closure_scope_(closure_scope),
38 factory_(ast_value_factory, zone_),
39 result_assigned_(
false),
42 DCHECK_EQ(closure_scope, closure_scope->GetClosureScope());
43 InitializeAstVisitor(parser->stack_limit());
47 bool result_assigned()
const {
return result_assigned_; }
49 Zone* zone() {
return zone_; }
55 result_assigned_ =
true;
56 VariableProxy* result_proxy = factory()->NewVariableProxy(result_);
57 return factory()->NewAssignment(Token::ASSIGN, result_proxy, value,
71 class BreakableScope final {
73 explicit BreakableScope(
Processor* processor,
bool breakable =
true)
74 : processor_(processor), previous_(processor->breakable_) {
75 processor->breakable_ = processor->breakable_ || breakable;
78 ~BreakableScope() { processor_->breakable_ = previous_; }
90 #define DEF_VISIT(type) void Visit##type(type* node); 91 AST_NODE_LIST(DEF_VISIT)
96 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
102 bool result_assigned_;
115 Expression* undef = factory()->NewUndefinedLiteral(kNoSourcePosition);
117 Block* b = factory()->NewBlock(2,
false);
118 b->statements()->Add(
119 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
120 b->statements()->Add(s, zone());
124 void Processor::Process(ZonePtrList<Statement>* statements) {
130 for (
int i = statements->length() - 1;
i >= 0 && (breakable_ || !is_set_);
132 Visit(statements->at(
i));
133 statements->Set(
i, replacement_);
138 void Processor::VisitBlock(Block* node) {
147 if (!node->ignore_completion_value()) {
148 BreakableScope scope(
this, node->labels() !=
nullptr);
149 Process(node->statements());
155 void Processor::VisitExpressionStatement(ExpressionStatement* node) {
158 node->set_expression(SetResult(node->expression()));
165 void Processor::VisitIfStatement(IfStatement* node) {
167 bool set_after = is_set_;
169 Visit(node->then_statement());
170 node->set_then_statement(replacement_);
171 bool set_in_then = is_set_;
174 Visit(node->else_statement());
175 node->set_else_statement(replacement_);
177 replacement_ = set_in_then && is_set_ ? node : AssignUndefinedBefore(node);
182 void Processor::VisitIterationStatement(IterationStatement* node) {
187 DCHECK(breakable_ || !is_set_);
188 BreakableScope scope(
this);
191 node->set_body(replacement_);
193 replacement_ = AssignUndefinedBefore(node);
198 void Processor::VisitDoWhileStatement(DoWhileStatement* node) {
199 VisitIterationStatement(node);
203 void Processor::VisitWhileStatement(WhileStatement* node) {
204 VisitIterationStatement(node);
208 void Processor::VisitForStatement(ForStatement* node) {
209 VisitIterationStatement(node);
213 void Processor::VisitForInStatement(ForInStatement* node) {
214 VisitIterationStatement(node);
218 void Processor::VisitForOfStatement(ForOfStatement* node) {
219 VisitIterationStatement(node);
223 void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
225 bool set_after = is_set_;
227 Visit(node->try_block());
228 node->set_try_block(static_cast<Block*>(replacement_));
229 bool set_in_try = is_set_;
232 Visit(node->catch_block());
233 node->set_catch_block(static_cast<Block*>(replacement_));
235 replacement_ = is_set_ && set_in_try ? node : AssignUndefinedBefore(node);
240 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
246 Visit(node->finally_block());
247 node->set_finally_block(replacement_->AsBlock());
252 CHECK_NOT_NULL(closure_scope());
253 Variable* backup = closure_scope()->NewTemporary(
254 factory()->ast_value_factory()->dot_result_string());
255 Expression* backup_proxy = factory()->NewVariableProxy(backup);
256 Expression* result_proxy = factory()->NewVariableProxy(result_);
257 Expression* save = factory()->NewAssignment(
258 Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition);
259 Expression* restore = factory()->NewAssignment(
260 Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition);
261 node->finally_block()->statements()->InsertAt(
262 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone());
263 node->finally_block()->statements()->Add(
264 factory()->NewExpressionStatement(restore, kNoSourcePosition), zone());
269 Visit(node->try_block());
270 node->set_try_block(replacement_->AsBlock());
272 replacement_ = is_set_ ? node : AssignUndefinedBefore(node);
277 void Processor::VisitSwitchStatement(SwitchStatement* node) {
282 DCHECK(breakable_ || !is_set_);
283 BreakableScope scope(
this);
285 ZonePtrList<CaseClause>* clauses = node->cases();
286 for (
int i = clauses->length() - 1;
i >= 0; --
i) {
287 CaseClause* clause = clauses->at(
i);
288 Process(clause->statements());
291 replacement_ = AssignUndefinedBefore(node);
296 void Processor::VisitContinueStatement(ContinueStatement* node) {
302 void Processor::VisitBreakStatement(BreakStatement* node) {
308 void Processor::VisitWithStatement(WithStatement* node) {
309 Visit(node->statement());
310 node->set_statement(replacement_);
312 replacement_ = is_set_ ? node : AssignUndefinedBefore(node);
317 void Processor::VisitSloppyBlockFunctionStatement(
318 SloppyBlockFunctionStatement* node) {
319 Visit(node->statement());
320 node->set_statement(replacement_);
325 void Processor::VisitEmptyStatement(EmptyStatement* node) {
330 void Processor::VisitReturnStatement(ReturnStatement* node) {
336 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {
340 void Processor::VisitInitializeClassMembersStatement(
341 InitializeClassMembersStatement* node) {
346 #define DEF_VISIT(type) \ 347 void Processor::Visit##type(type* expr) { UNREACHABLE(); } 348 EXPRESSION_NODE_LIST(DEF_VISIT)
353 #define DEF_VISIT(type) \ 354 void Processor::Visit##type(type* expr) { UNREACHABLE(); } 355 DECLARATION_NODE_LIST(DEF_VISIT)
361 bool Rewriter::Rewrite(ParseInfo* info) {
362 DisallowHeapAllocation no_allocation;
363 DisallowHandleAllocation no_handles;
364 DisallowHandleDereference no_deref;
366 RuntimeCallTimerScope runtimeTimer(
367 info->runtime_call_stats(),
368 info->on_background_thread()
369 ? RuntimeCallCounterId::kCompileBackgroundRewriteReturnResult
370 : RuntimeCallCounterId::kCompileRewriteReturnResult);
372 FunctionLiteral*
function = info->literal();
373 DCHECK_NOT_NULL(
function);
374 Scope* scope =
function->scope();
375 DCHECK_NOT_NULL(scope);
376 DCHECK_EQ(scope, scope->GetClosureScope());
378 if (!(scope->is_script_scope() || scope->is_eval_scope() ||
379 scope->is_module_scope())) {
383 ZonePtrList<Statement>* body =
function->body();
384 DCHECK_IMPLIES(scope->is_module_scope(), !body->is_empty());
385 if (!body->is_empty()) {
386 Variable* result = scope->AsDeclarationScope()->NewTemporary(
387 info->ast_value_factory()->dot_result_string());
388 Processor processor(info->stack_limit(), scope->AsDeclarationScope(),
389 result, info->ast_value_factory());
390 processor.Process(body);
392 DCHECK_IMPLIES(scope->is_module_scope(), processor.result_assigned());
393 if (processor.result_assigned()) {
394 int pos = kNoSourcePosition;
395 Expression* result_value =
396 processor.factory()->NewVariableProxy(result, pos);
397 Statement* result_statement =
398 processor.factory()->NewReturnStatement(result_value, pos);
399 body->Add(result_statement, info->zone());
402 if (processor.HasStackOverflow())
return false;