blob: 272f9bde1128b64e4e7fd0615cd65a837f49f3c6 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
3// found in the LICENSE file.
4
5#include "src/ast/ast-numbering.h"
6
7#include "src/ast/ast.h"
8#include "src/ast/scopes.h"
9
10namespace v8 {
11namespace internal {
12
13class AstNumberingVisitor final : public AstVisitor {
14 public:
15 AstNumberingVisitor(Isolate* isolate, Zone* zone)
16 : AstVisitor(),
17 isolate_(isolate),
18 zone_(zone),
19 next_id_(BailoutId::FirstUsable().ToInt()),
20 properties_(zone),
21 slot_cache_(zone),
22 dont_optimize_reason_(kNoReason) {
23 InitializeAstVisitor(isolate);
24 }
25
26 bool Renumber(FunctionLiteral* node);
27
28 private:
29// AST node visitor interface.
30#define DEFINE_VISIT(type) void Visit##type(type* node) override;
31 AST_NODE_LIST(DEFINE_VISIT)
32#undef DEFINE_VISIT
33
34 bool Finish(FunctionLiteral* node);
35
36 void VisitVariableProxyReference(VariableProxy* node);
37 void VisitPropertyReference(Property* node);
38 void VisitReference(Expression* expr);
39
40 void VisitStatements(ZoneList<Statement*>* statements) override;
41 void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
42 void VisitArguments(ZoneList<Expression*>* arguments);
43 void VisitObjectLiteralProperty(ObjectLiteralProperty* property);
44
45 int ReserveIdRange(int n) {
46 int tmp = next_id_;
47 next_id_ += n;
48 return tmp;
49 }
50
51 void IncrementNodeCount() { properties_.add_node_count(1); }
52 void DisableSelfOptimization() {
53 properties_.flags() |= AstProperties::kDontSelfOptimize;
54 }
55 void DisableOptimization(BailoutReason reason) {
56 dont_optimize_reason_ = reason;
57 DisableSelfOptimization();
58 }
59 void DisableCrankshaft(BailoutReason reason) {
60 if (FLAG_turbo_shipping) {
61 properties_.flags() |= AstProperties::kDontCrankshaft;
62 } else {
63 dont_optimize_reason_ = reason;
64 DisableSelfOptimization();
65 }
66 }
67
68 template <typename Node>
69 void ReserveFeedbackSlots(Node* node) {
70 node->AssignFeedbackVectorSlots(isolate_, properties_.get_spec(),
71 &slot_cache_);
72 }
73
74 BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; }
75
76 Isolate* isolate_;
77 Zone* zone_;
78 int next_id_;
79 AstProperties properties_;
80 // The slot cache allows us to reuse certain feedback vector slots.
81 FeedbackVectorSlotCache slot_cache_;
82 BailoutReason dont_optimize_reason_;
83
84 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
85 DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
86};
87
88
89void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) {
90 IncrementNodeCount();
91 VisitVariableProxy(node->proxy());
92}
93
94
95void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) {
96 IncrementNodeCount();
97 DisableOptimization(kExportDeclaration);
98 VisitVariableProxy(node->proxy());
99}
100
101
102void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {
103 IncrementNodeCount();
104}
105
106
107void AstNumberingVisitor::VisitSloppyBlockFunctionStatement(
108 SloppyBlockFunctionStatement* node) {
109 IncrementNodeCount();
110 Visit(node->statement());
111}
112
113
114void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {
115 IncrementNodeCount();
116}
117
118
119void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {
120 IncrementNodeCount();
121}
122
123
124void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
125 IncrementNodeCount();
126 DisableOptimization(kDebuggerStatement);
127 node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids()));
128}
129
130
131void AstNumberingVisitor::VisitNativeFunctionLiteral(
132 NativeFunctionLiteral* node) {
133 IncrementNodeCount();
134 DisableOptimization(kNativeFunctionLiteral);
135 node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
136}
137
138
139void AstNumberingVisitor::VisitDoExpression(DoExpression* node) {
140 IncrementNodeCount();
141 DisableCrankshaft(kDoExpression);
142 node->set_base_id(ReserveIdRange(DoExpression::num_ids()));
143 Visit(node->block());
144 Visit(node->result());
145}
146
147
148void AstNumberingVisitor::VisitLiteral(Literal* node) {
149 IncrementNodeCount();
150 node->set_base_id(ReserveIdRange(Literal::num_ids()));
151}
152
153
154void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
155 IncrementNodeCount();
156 node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
157}
158
159
160void AstNumberingVisitor::VisitVariableProxyReference(VariableProxy* node) {
161 IncrementNodeCount();
162 if (node->var()->IsLookupSlot()) {
163 DisableCrankshaft(kReferenceToAVariableWhichRequiresDynamicLookup);
164 }
165 node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
166}
167
168
169void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
170 VisitVariableProxyReference(node);
171 ReserveFeedbackSlots(node);
172}
173
174
175void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
176 IncrementNodeCount();
177 node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
178}
179
180
181void AstNumberingVisitor::VisitSuperPropertyReference(
182 SuperPropertyReference* node) {
183 IncrementNodeCount();
184 DisableCrankshaft(kSuperReference);
185 node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids()));
186 Visit(node->this_var());
187 Visit(node->home_object());
188}
189
190
191void AstNumberingVisitor::VisitSuperCallReference(SuperCallReference* node) {
192 IncrementNodeCount();
193 DisableCrankshaft(kSuperReference);
194 node->set_base_id(ReserveIdRange(SuperCallReference::num_ids()));
195 Visit(node->this_var());
196 Visit(node->new_target_var());
197 Visit(node->this_function_var());
198}
199
200
201void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
202 IncrementNodeCount();
203 DisableOptimization(kImportDeclaration);
204 VisitVariableProxy(node->proxy());
205}
206
207
208void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
209 IncrementNodeCount();
210 Visit(node->expression());
211}
212
213
214void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
215 IncrementNodeCount();
216 Visit(node->expression());
217}
218
219
220void AstNumberingVisitor::VisitYield(Yield* node) {
221 IncrementNodeCount();
222 DisableOptimization(kYield);
223 ReserveFeedbackSlots(node);
224 node->set_base_id(ReserveIdRange(Yield::num_ids()));
225 Visit(node->generator_object());
226 Visit(node->expression());
227}
228
229
230void AstNumberingVisitor::VisitThrow(Throw* node) {
231 IncrementNodeCount();
232 node->set_base_id(ReserveIdRange(Throw::num_ids()));
233 Visit(node->exception());
234}
235
236
237void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
238 IncrementNodeCount();
239 node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
240 Visit(node->expression());
241}
242
243
244void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
245 IncrementNodeCount();
246 node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
247 Visit(node->expression());
248 ReserveFeedbackSlots(node);
249}
250
251
252void AstNumberingVisitor::VisitBlock(Block* node) {
253 IncrementNodeCount();
254 node->set_base_id(ReserveIdRange(Block::num_ids()));
255 if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations());
256 VisitStatements(node->statements());
257}
258
259
260void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
261 IncrementNodeCount();
262 VisitVariableProxy(node->proxy());
263 VisitFunctionLiteral(node->fun());
264}
265
266
267void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
268 IncrementNodeCount();
269 ReserveFeedbackSlots(node);
270 if (node->is_jsruntime()) {
271 // Don't try to optimize JS runtime calls because we bailout on them.
272 DisableOptimization(kCallToAJavaScriptRuntimeFunction);
273 }
274 node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
275 VisitArguments(node->arguments());
276}
277
278
279void AstNumberingVisitor::VisitWithStatement(WithStatement* node) {
280 IncrementNodeCount();
281 DisableCrankshaft(kWithStatement);
282 node->set_base_id(ReserveIdRange(WithStatement::num_ids()));
283 Visit(node->expression());
284 Visit(node->statement());
285}
286
287
288void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
289 IncrementNodeCount();
290 DisableSelfOptimization();
291 node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
292 Visit(node->body());
293 Visit(node->cond());
294}
295
296
297void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) {
298 IncrementNodeCount();
299 DisableSelfOptimization();
300 node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
301 Visit(node->cond());
302 Visit(node->body());
303}
304
305
306void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
307 IncrementNodeCount();
308 DisableOptimization(kTryCatchStatement);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 Visit(node->try_block());
310 Visit(node->catch_block());
311}
312
313
314void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
315 IncrementNodeCount();
316 DisableOptimization(kTryFinallyStatement);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 Visit(node->try_block());
318 Visit(node->finally_block());
319}
320
321
322void AstNumberingVisitor::VisitPropertyReference(Property* node) {
323 IncrementNodeCount();
324 node->set_base_id(ReserveIdRange(Property::num_ids()));
325 Visit(node->key());
326 Visit(node->obj());
327}
328
329
330void AstNumberingVisitor::VisitReference(Expression* expr) {
331 DCHECK(expr->IsProperty() || expr->IsVariableProxy());
332 if (expr->IsProperty()) {
333 VisitPropertyReference(expr->AsProperty());
334 } else {
335 VisitVariableProxyReference(expr->AsVariableProxy());
336 }
337}
338
339
340void AstNumberingVisitor::VisitProperty(Property* node) {
341 VisitPropertyReference(node);
342 ReserveFeedbackSlots(node);
343}
344
345
346void AstNumberingVisitor::VisitAssignment(Assignment* node) {
347 IncrementNodeCount();
348 node->set_base_id(ReserveIdRange(Assignment::num_ids()));
349
350 if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
351 VisitReference(node->target());
352 Visit(node->value());
353 ReserveFeedbackSlots(node);
354}
355
356
357void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
358 IncrementNodeCount();
359 node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
360 Visit(node->left());
361 Visit(node->right());
362}
363
364
365void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
366 IncrementNodeCount();
367 node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
368 Visit(node->left());
369 Visit(node->right());
370}
371
372
Ben Murdoch097c5b22016-05-18 11:27:45 +0100373void AstNumberingVisitor::VisitSpread(Spread* node) { UNREACHABLE(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374
375
376void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) {
377 UNREACHABLE();
378}
379
380
381void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
382 IncrementNodeCount();
383 DisableSelfOptimization();
384 node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
385 Visit(node->each());
386 Visit(node->enumerable());
387 Visit(node->body());
388 ReserveFeedbackSlots(node);
389}
390
391
392void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
393 IncrementNodeCount();
394 DisableCrankshaft(kForOfStatement);
395 node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
396 Visit(node->assign_iterator());
397 Visit(node->next_result());
398 Visit(node->result_done());
399 Visit(node->assign_each());
400 Visit(node->body());
401 ReserveFeedbackSlots(node);
402}
403
404
405void AstNumberingVisitor::VisitConditional(Conditional* node) {
406 IncrementNodeCount();
407 node->set_base_id(ReserveIdRange(Conditional::num_ids()));
408 Visit(node->condition());
409 Visit(node->then_expression());
410 Visit(node->else_expression());
411}
412
413
414void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
415 IncrementNodeCount();
416 node->set_base_id(ReserveIdRange(IfStatement::num_ids()));
417 Visit(node->condition());
418 Visit(node->then_statement());
419 if (node->HasElseStatement()) {
420 Visit(node->else_statement());
421 }
422}
423
424
425void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
426 IncrementNodeCount();
427 node->set_base_id(ReserveIdRange(SwitchStatement::num_ids()));
428 Visit(node->tag());
429 ZoneList<CaseClause*>* cases = node->cases();
430 for (int i = 0; i < cases->length(); i++) {
431 VisitCaseClause(cases->at(i));
432 }
433}
434
435
436void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
437 IncrementNodeCount();
438 node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
439 if (!node->is_default()) Visit(node->label());
440 VisitStatements(node->statements());
441}
442
443
444void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
445 IncrementNodeCount();
446 DisableSelfOptimization();
447 node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
448 if (node->init() != NULL) Visit(node->init());
449 if (node->cond() != NULL) Visit(node->cond());
450 if (node->next() != NULL) Visit(node->next());
451 Visit(node->body());
452}
453
454
455void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
456 IncrementNodeCount();
457 DisableCrankshaft(kClassLiteral);
458 node->set_base_id(ReserveIdRange(node->num_ids()));
459 if (node->extends()) Visit(node->extends());
460 if (node->constructor()) Visit(node->constructor());
461 if (node->class_variable_proxy()) {
462 VisitVariableProxy(node->class_variable_proxy());
463 }
464 for (int i = 0; i < node->properties()->length(); i++) {
465 VisitObjectLiteralProperty(node->properties()->at(i));
466 }
467 ReserveFeedbackSlots(node);
468}
469
470
471void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
472 IncrementNodeCount();
473 node->set_base_id(ReserveIdRange(node->num_ids()));
474 for (int i = 0; i < node->properties()->length(); i++) {
475 VisitObjectLiteralProperty(node->properties()->at(i));
476 }
477 node->BuildConstantProperties(isolate_);
478 // Mark all computed expressions that are bound to a key that
479 // is shadowed by a later occurrence of the same key. For the
480 // marked expressions, no store code will be is emitted.
481 node->CalculateEmitStore(zone_);
482 ReserveFeedbackSlots(node);
483}
484
485
486void AstNumberingVisitor::VisitObjectLiteralProperty(
487 ObjectLiteralProperty* node) {
488 if (node->is_computed_name()) DisableCrankshaft(kComputedPropertyName);
489 Visit(node->key());
490 Visit(node->value());
491}
492
493
494void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
495 IncrementNodeCount();
496 node->set_base_id(ReserveIdRange(node->num_ids()));
497 for (int i = 0; i < node->values()->length(); i++) {
498 Visit(node->values()->at(i));
499 }
500 node->BuildConstantElements(isolate_);
501 ReserveFeedbackSlots(node);
502}
503
504
505void AstNumberingVisitor::VisitCall(Call* node) {
506 IncrementNodeCount();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100507 if (node->tail_call_mode() == TailCallMode::kAllow) {
508 DisableOptimization(kTailCall);
509 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 ReserveFeedbackSlots(node);
511 node->set_base_id(ReserveIdRange(Call::num_ids()));
512 Visit(node->expression());
513 VisitArguments(node->arguments());
514}
515
516
517void AstNumberingVisitor::VisitCallNew(CallNew* node) {
518 IncrementNodeCount();
519 ReserveFeedbackSlots(node);
520 node->set_base_id(ReserveIdRange(CallNew::num_ids()));
521 Visit(node->expression());
522 VisitArguments(node->arguments());
523}
524
525
526void AstNumberingVisitor::VisitStatements(ZoneList<Statement*>* statements) {
527 if (statements == NULL) return;
528 for (int i = 0; i < statements->length(); i++) {
529 Visit(statements->at(i));
530 }
531}
532
533
534void AstNumberingVisitor::VisitDeclarations(
535 ZoneList<Declaration*>* declarations) {
536 for (int i = 0; i < declarations->length(); i++) {
537 Visit(declarations->at(i));
538 }
539}
540
541
542void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) {
543 for (int i = 0; i < arguments->length(); i++) {
544 Visit(arguments->at(i));
545 }
546}
547
548
549void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
550 IncrementNodeCount();
551 node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids()));
552 // We don't recurse into the declarations or body of the function literal:
553 // you have to separately Renumber() each FunctionLiteral that you compile.
554}
555
556
Ben Murdoch097c5b22016-05-18 11:27:45 +0100557void AstNumberingVisitor::VisitRewritableExpression(
558 RewritableExpression* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000559 IncrementNodeCount();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100560 node->set_base_id(ReserveIdRange(RewritableExpression::num_ids()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 Visit(node->expression());
562}
563
564
565bool AstNumberingVisitor::Finish(FunctionLiteral* node) {
566 node->set_ast_properties(&properties_);
567 node->set_dont_optimize_reason(dont_optimize_reason());
568 return !HasStackOverflow();
569}
570
571
572bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
573 Scope* scope = node->scope();
574
575 if (scope->HasIllegalRedeclaration()) {
576 Visit(scope->GetIllegalRedeclaration());
577 DisableOptimization(kFunctionWithIllegalRedeclaration);
578 return Finish(node);
579 }
580 if (scope->new_target_var()) DisableCrankshaft(kSuperReference);
581 if (scope->calls_eval()) DisableOptimization(kFunctionCallsEval);
582 if (scope->arguments() != NULL && !scope->arguments()->IsStackAllocated()) {
583 DisableCrankshaft(kContextAllocatedArguments);
584 }
585
586 int rest_index;
587 if (scope->rest_parameter(&rest_index)) {
588 DisableCrankshaft(kRestParameter);
589 }
590
591 VisitDeclarations(scope->declarations());
592 VisitStatements(node->body());
593
594 return Finish(node);
595}
596
597
598bool AstNumbering::Renumber(Isolate* isolate, Zone* zone,
599 FunctionLiteral* function) {
600 AstNumberingVisitor visitor(isolate, zone);
601 return visitor.Renumber(function);
602}
603} // namespace internal
604} // namespace v8