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
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 #include "src/compiler.h"
10 #include "src/objects-inl.h"
11
12 namespace v8 {
13 namespace internal {
14
15 class AstNumberingVisitor final : public AstVisitor<AstNumberingVisitor> {
16 public:
AstNumberingVisitor(uintptr_t stack_limit,Zone * zone,Compiler::EagerInnerFunctionLiterals * eager_literals)17 AstNumberingVisitor(uintptr_t stack_limit, Zone* zone,
18 Compiler::EagerInnerFunctionLiterals* eager_literals)
19 : zone_(zone),
20 eager_literals_(eager_literals),
21 next_id_(BailoutId::FirstUsable().ToInt()),
22 yield_count_(0),
23 properties_(zone),
24 language_mode_(SLOPPY),
25 slot_cache_(zone),
26 disable_crankshaft_reason_(kNoReason),
27 dont_optimize_reason_(kNoReason),
28 catch_prediction_(HandlerTable::UNCAUGHT) {
29 InitializeAstVisitor(stack_limit);
30 }
31
32 bool Renumber(FunctionLiteral* node);
33
34 private:
35 // AST node visitor interface.
36 #define DEFINE_VISIT(type) void Visit##type(type* node);
37 AST_NODE_LIST(DEFINE_VISIT)
38 #undef DEFINE_VISIT
39
40 void VisitVariableProxy(VariableProxy* node, TypeofMode typeof_mode);
41 void VisitVariableProxyReference(VariableProxy* node);
42 void VisitPropertyReference(Property* node);
43 void VisitReference(Expression* expr);
44
45 void VisitStatementsAndDeclarations(Block* node);
46 void VisitStatements(ZoneList<Statement*>* statements);
47 void VisitDeclarations(Declaration::List* declarations);
48 void VisitArguments(ZoneList<Expression*>* arguments);
49 void VisitLiteralProperty(LiteralProperty* property);
50
ReserveIdRange(int n)51 int ReserveIdRange(int n) {
52 int tmp = next_id_;
53 next_id_ += n;
54 return tmp;
55 }
56
IncrementNodeCount()57 void IncrementNodeCount() { properties_.add_node_count(1); }
DisableSelfOptimization()58 void DisableSelfOptimization() {
59 properties_.flags() |= AstProperties::kDontSelfOptimize;
60 }
DisableOptimization(BailoutReason reason)61 void DisableOptimization(BailoutReason reason) {
62 dont_optimize_reason_ = reason;
63 DisableSelfOptimization();
64 }
DisableFullCodegenAndCrankshaft(BailoutReason reason)65 void DisableFullCodegenAndCrankshaft(BailoutReason reason) {
66 disable_crankshaft_reason_ = reason;
67 properties_.flags() |= AstProperties::kMustUseIgnitionTurbo;
68 }
69
70 template <typename Node>
ReserveFeedbackSlots(Node * node)71 void ReserveFeedbackSlots(Node* node) {
72 node->AssignFeedbackSlots(properties_.get_spec(), language_mode_,
73 &slot_cache_);
74 }
75
76 class LanguageModeScope {
77 public:
LanguageModeScope(AstNumberingVisitor * visitor,LanguageMode language_mode)78 LanguageModeScope(AstNumberingVisitor* visitor, LanguageMode language_mode)
79 : visitor_(visitor), outer_language_mode_(visitor->language_mode_) {
80 visitor_->language_mode_ = language_mode;
81 }
~LanguageModeScope()82 ~LanguageModeScope() { visitor_->language_mode_ = outer_language_mode_; }
83
84 private:
85 AstNumberingVisitor* visitor_;
86 LanguageMode outer_language_mode_;
87 };
88
dont_optimize_reason() const89 BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; }
90
zone() const91 Zone* zone() const { return zone_; }
92
93 Zone* zone_;
94 Compiler::EagerInnerFunctionLiterals* eager_literals_;
95 int next_id_;
96 int yield_count_;
97 AstProperties properties_;
98 LanguageMode language_mode_;
99 // The slot cache allows us to reuse certain feedback slots.
100 FeedbackSlotCache slot_cache_;
101 BailoutReason disable_crankshaft_reason_;
102 BailoutReason dont_optimize_reason_;
103 HandlerTable::CatchPrediction catch_prediction_;
104
105 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
106 DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
107 };
108
109
VisitVariableDeclaration(VariableDeclaration * node)110 void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) {
111 IncrementNodeCount();
112 VisitVariableProxy(node->proxy());
113 }
114
115
VisitEmptyStatement(EmptyStatement * node)116 void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {
117 IncrementNodeCount();
118 }
119
120
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * node)121 void AstNumberingVisitor::VisitSloppyBlockFunctionStatement(
122 SloppyBlockFunctionStatement* node) {
123 IncrementNodeCount();
124 Visit(node->statement());
125 }
126
127
VisitContinueStatement(ContinueStatement * node)128 void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {
129 IncrementNodeCount();
130 }
131
132
VisitBreakStatement(BreakStatement * node)133 void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {
134 IncrementNodeCount();
135 }
136
137
VisitDebuggerStatement(DebuggerStatement * node)138 void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
139 IncrementNodeCount();
140 DisableFullCodegenAndCrankshaft(kDebuggerStatement);
141 }
142
143
VisitNativeFunctionLiteral(NativeFunctionLiteral * node)144 void AstNumberingVisitor::VisitNativeFunctionLiteral(
145 NativeFunctionLiteral* node) {
146 IncrementNodeCount();
147 DisableOptimization(kNativeFunctionLiteral);
148 node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
149 ReserveFeedbackSlots(node);
150 }
151
152
VisitDoExpression(DoExpression * node)153 void AstNumberingVisitor::VisitDoExpression(DoExpression* node) {
154 IncrementNodeCount();
155 node->set_base_id(ReserveIdRange(DoExpression::num_ids()));
156 Visit(node->block());
157 Visit(node->result());
158 }
159
160
VisitLiteral(Literal * node)161 void AstNumberingVisitor::VisitLiteral(Literal* node) {
162 IncrementNodeCount();
163 node->set_base_id(ReserveIdRange(Literal::num_ids()));
164 }
165
166
VisitRegExpLiteral(RegExpLiteral * node)167 void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
168 IncrementNodeCount();
169 node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
170 ReserveFeedbackSlots(node);
171 }
172
173
VisitVariableProxyReference(VariableProxy * node)174 void AstNumberingVisitor::VisitVariableProxyReference(VariableProxy* node) {
175 IncrementNodeCount();
176 switch (node->var()->location()) {
177 case VariableLocation::LOOKUP:
178 DisableFullCodegenAndCrankshaft(
179 kReferenceToAVariableWhichRequiresDynamicLookup);
180 break;
181 case VariableLocation::MODULE:
182 DisableFullCodegenAndCrankshaft(kReferenceToModuleVariable);
183 break;
184 default:
185 break;
186 }
187 node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
188 }
189
VisitVariableProxy(VariableProxy * node,TypeofMode typeof_mode)190 void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node,
191 TypeofMode typeof_mode) {
192 VisitVariableProxyReference(node);
193 node->AssignFeedbackSlots(properties_.get_spec(), typeof_mode, &slot_cache_);
194 }
195
VisitVariableProxy(VariableProxy * node)196 void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
197 VisitVariableProxy(node, NOT_INSIDE_TYPEOF);
198 }
199
200
VisitThisFunction(ThisFunction * node)201 void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
202 IncrementNodeCount();
203 node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
204 }
205
206
VisitSuperPropertyReference(SuperPropertyReference * node)207 void AstNumberingVisitor::VisitSuperPropertyReference(
208 SuperPropertyReference* node) {
209 IncrementNodeCount();
210 DisableFullCodegenAndCrankshaft(kSuperReference);
211 node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids()));
212 Visit(node->this_var());
213 Visit(node->home_object());
214 }
215
216
VisitSuperCallReference(SuperCallReference * node)217 void AstNumberingVisitor::VisitSuperCallReference(SuperCallReference* node) {
218 IncrementNodeCount();
219 DisableFullCodegenAndCrankshaft(kSuperReference);
220 node->set_base_id(ReserveIdRange(SuperCallReference::num_ids()));
221 Visit(node->this_var());
222 Visit(node->new_target_var());
223 Visit(node->this_function_var());
224 }
225
226
VisitExpressionStatement(ExpressionStatement * node)227 void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
228 IncrementNodeCount();
229 Visit(node->expression());
230 }
231
232
VisitReturnStatement(ReturnStatement * node)233 void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
234 IncrementNodeCount();
235 Visit(node->expression());
236
237 DCHECK(!node->is_async_return() ||
238 properties_.flags() & AstProperties::kMustUseIgnitionTurbo);
239 }
240
241
VisitYield(Yield * node)242 void AstNumberingVisitor::VisitYield(Yield* node) {
243 node->set_yield_id(yield_count_);
244 yield_count_++;
245 IncrementNodeCount();
246 node->set_base_id(ReserveIdRange(Yield::num_ids()));
247 Visit(node->generator_object());
248 Visit(node->expression());
249 }
250
251
VisitThrow(Throw * node)252 void AstNumberingVisitor::VisitThrow(Throw* node) {
253 IncrementNodeCount();
254 node->set_base_id(ReserveIdRange(Throw::num_ids()));
255 Visit(node->exception());
256 }
257
258
VisitUnaryOperation(UnaryOperation * node)259 void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
260 IncrementNodeCount();
261 node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
262 if ((node->op() == Token::TYPEOF) && node->expression()->IsVariableProxy()) {
263 VariableProxy* proxy = node->expression()->AsVariableProxy();
264 VisitVariableProxy(proxy, INSIDE_TYPEOF);
265 } else {
266 Visit(node->expression());
267 }
268 }
269
270
VisitCountOperation(CountOperation * node)271 void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
272 IncrementNodeCount();
273 node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
274 Visit(node->expression());
275 ReserveFeedbackSlots(node);
276 }
277
278
VisitBlock(Block * node)279 void AstNumberingVisitor::VisitBlock(Block* node) {
280 IncrementNodeCount();
281 node->set_base_id(ReserveIdRange(Block::num_ids()));
282 Scope* scope = node->scope();
283 if (scope != nullptr) {
284 LanguageModeScope language_mode_scope(this, scope->language_mode());
285 VisitStatementsAndDeclarations(node);
286 } else {
287 VisitStatementsAndDeclarations(node);
288 }
289 }
290
VisitStatementsAndDeclarations(Block * node)291 void AstNumberingVisitor::VisitStatementsAndDeclarations(Block* node) {
292 Scope* scope = node->scope();
293 DCHECK(scope == nullptr || !scope->HasBeenRemoved());
294 if (scope) VisitDeclarations(scope->declarations());
295 VisitStatements(node->statements());
296 }
297
VisitFunctionDeclaration(FunctionDeclaration * node)298 void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
299 IncrementNodeCount();
300 VisitVariableProxy(node->proxy());
301 VisitFunctionLiteral(node->fun());
302 }
303
304
VisitCallRuntime(CallRuntime * node)305 void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
306 IncrementNodeCount();
307 node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
308 VisitArguments(node->arguments());
309 // To support catch prediction within async/await:
310 //
311 // The AstNumberingVisitor is when catch prediction currently occurs, and it
312 // is the only common point that has access to this information. The parser
313 // just doesn't know yet. Take the following two cases of catch prediction:
314 //
315 // try { await fn(); } catch (e) { }
316 // try { await fn(); } finally { }
317 //
318 // When parsing the await that we want to mark as caught or uncaught, it's
319 // not yet known whether it will be followed by a 'finally' or a 'catch.
320 // The AstNumberingVisitor is what learns whether it is caught. To make
321 // the information available later to the runtime, the AstNumberingVisitor
322 // has to stash it somewhere. Changing the runtime function into another
323 // one in ast-numbering seemed like a simple and straightforward solution to
324 // that problem.
325 if (node->is_jsruntime() &&
326 node->context_index() == Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX &&
327 catch_prediction_ == HandlerTable::ASYNC_AWAIT) {
328 node->set_context_index(Context::ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX);
329 }
330 }
331
332
VisitWithStatement(WithStatement * node)333 void AstNumberingVisitor::VisitWithStatement(WithStatement* node) {
334 IncrementNodeCount();
335 DisableFullCodegenAndCrankshaft(kWithStatement);
336 Visit(node->expression());
337 Visit(node->statement());
338 }
339
340
VisitDoWhileStatement(DoWhileStatement * node)341 void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
342 IncrementNodeCount();
343 DisableSelfOptimization();
344 node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
345 node->set_first_yield_id(yield_count_);
346 Visit(node->body());
347 Visit(node->cond());
348 node->set_yield_count(yield_count_ - node->first_yield_id());
349 }
350
351
VisitWhileStatement(WhileStatement * node)352 void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) {
353 IncrementNodeCount();
354 DisableSelfOptimization();
355 node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
356 node->set_first_yield_id(yield_count_);
357 Visit(node->cond());
358 Visit(node->body());
359 node->set_yield_count(yield_count_ - node->first_yield_id());
360 }
361
362
VisitTryCatchStatement(TryCatchStatement * node)363 void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
364 DCHECK(node->scope() == nullptr || !node->scope()->HasBeenRemoved());
365 IncrementNodeCount();
366 DisableFullCodegenAndCrankshaft(kTryCatchStatement);
367 {
368 const HandlerTable::CatchPrediction old_prediction = catch_prediction_;
369 // This node uses its own prediction, unless it's "uncaught", in which case
370 // we adopt the prediction of the outer try-block.
371 HandlerTable::CatchPrediction catch_prediction = node->catch_prediction();
372 if (catch_prediction != HandlerTable::UNCAUGHT) {
373 catch_prediction_ = catch_prediction;
374 }
375 node->set_catch_prediction(catch_prediction_);
376 Visit(node->try_block());
377 catch_prediction_ = old_prediction;
378 }
379 Visit(node->catch_block());
380 }
381
382
VisitTryFinallyStatement(TryFinallyStatement * node)383 void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
384 IncrementNodeCount();
385 DisableFullCodegenAndCrankshaft(kTryFinallyStatement);
386 // We can't know whether the finally block will override ("catch") an
387 // exception thrown in the try block, so we just adopt the outer prediction.
388 node->set_catch_prediction(catch_prediction_);
389 Visit(node->try_block());
390 Visit(node->finally_block());
391 }
392
393
VisitPropertyReference(Property * node)394 void AstNumberingVisitor::VisitPropertyReference(Property* node) {
395 IncrementNodeCount();
396 node->set_base_id(ReserveIdRange(Property::num_ids()));
397 Visit(node->key());
398 Visit(node->obj());
399 }
400
401
VisitReference(Expression * expr)402 void AstNumberingVisitor::VisitReference(Expression* expr) {
403 DCHECK(expr->IsProperty() || expr->IsVariableProxy());
404 if (expr->IsProperty()) {
405 VisitPropertyReference(expr->AsProperty());
406 } else {
407 VisitVariableProxyReference(expr->AsVariableProxy());
408 }
409 }
410
411
VisitProperty(Property * node)412 void AstNumberingVisitor::VisitProperty(Property* node) {
413 VisitPropertyReference(node);
414 ReserveFeedbackSlots(node);
415 }
416
417
VisitAssignment(Assignment * node)418 void AstNumberingVisitor::VisitAssignment(Assignment* node) {
419 IncrementNodeCount();
420 node->set_base_id(ReserveIdRange(Assignment::num_ids()));
421
422 if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
423 VisitReference(node->target());
424 Visit(node->value());
425 ReserveFeedbackSlots(node);
426 }
427
428
VisitBinaryOperation(BinaryOperation * node)429 void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
430 IncrementNodeCount();
431 node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
432 Visit(node->left());
433 Visit(node->right());
434 ReserveFeedbackSlots(node);
435 }
436
437
VisitCompareOperation(CompareOperation * node)438 void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
439 IncrementNodeCount();
440 node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
441 Visit(node->left());
442 Visit(node->right());
443 ReserveFeedbackSlots(node);
444 }
445
VisitSpread(Spread * node)446 void AstNumberingVisitor::VisitSpread(Spread* node) {
447 IncrementNodeCount();
448 // We can only get here from spread calls currently.
449 DisableFullCodegenAndCrankshaft(kSpreadCall);
450 node->set_base_id(ReserveIdRange(Spread::num_ids()));
451 Visit(node->expression());
452 }
453
VisitEmptyParentheses(EmptyParentheses * node)454 void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) {
455 UNREACHABLE();
456 }
457
VisitGetIterator(GetIterator * node)458 void AstNumberingVisitor::VisitGetIterator(GetIterator* node) {
459 IncrementNodeCount();
460 DisableFullCodegenAndCrankshaft(kGetIterator);
461 node->set_base_id(ReserveIdRange(GetIterator::num_ids()));
462 Visit(node->iterable());
463 ReserveFeedbackSlots(node);
464 }
465
VisitForInStatement(ForInStatement * node)466 void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
467 IncrementNodeCount();
468 DisableSelfOptimization();
469 node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
470 Visit(node->enumerable()); // Not part of loop.
471 node->set_first_yield_id(yield_count_);
472 Visit(node->each());
473 Visit(node->body());
474 node->set_yield_count(yield_count_ - node->first_yield_id());
475 ReserveFeedbackSlots(node);
476 }
477
478
VisitForOfStatement(ForOfStatement * node)479 void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
480 IncrementNodeCount();
481 DisableFullCodegenAndCrankshaft(kForOfStatement);
482 node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
483 Visit(node->assign_iterator()); // Not part of loop.
484 node->set_first_yield_id(yield_count_);
485 Visit(node->next_result());
486 Visit(node->result_done());
487 Visit(node->assign_each());
488 Visit(node->body());
489 node->set_yield_count(yield_count_ - node->first_yield_id());
490 }
491
492
VisitConditional(Conditional * node)493 void AstNumberingVisitor::VisitConditional(Conditional* node) {
494 IncrementNodeCount();
495 node->set_base_id(ReserveIdRange(Conditional::num_ids()));
496 Visit(node->condition());
497 Visit(node->then_expression());
498 Visit(node->else_expression());
499 }
500
501
VisitIfStatement(IfStatement * node)502 void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
503 IncrementNodeCount();
504 node->set_base_id(ReserveIdRange(IfStatement::num_ids()));
505 Visit(node->condition());
506 Visit(node->then_statement());
507 if (node->HasElseStatement()) {
508 Visit(node->else_statement());
509 }
510 }
511
512
VisitSwitchStatement(SwitchStatement * node)513 void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
514 IncrementNodeCount();
515 node->set_base_id(ReserveIdRange(SwitchStatement::num_ids()));
516 Visit(node->tag());
517 ZoneList<CaseClause*>* cases = node->cases();
518 for (int i = 0; i < cases->length(); i++) {
519 VisitCaseClause(cases->at(i));
520 }
521 }
522
523
VisitCaseClause(CaseClause * node)524 void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
525 IncrementNodeCount();
526 node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
527 if (!node->is_default()) Visit(node->label());
528 VisitStatements(node->statements());
529 ReserveFeedbackSlots(node);
530 }
531
532
VisitForStatement(ForStatement * node)533 void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
534 IncrementNodeCount();
535 DisableSelfOptimization();
536 node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
537 if (node->init() != NULL) Visit(node->init()); // Not part of loop.
538 node->set_first_yield_id(yield_count_);
539 if (node->cond() != NULL) Visit(node->cond());
540 if (node->next() != NULL) Visit(node->next());
541 Visit(node->body());
542 node->set_yield_count(yield_count_ - node->first_yield_id());
543 }
544
545
VisitClassLiteral(ClassLiteral * node)546 void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
547 IncrementNodeCount();
548 DisableFullCodegenAndCrankshaft(kClassLiteral);
549 node->set_base_id(ReserveIdRange(ClassLiteral::num_ids()));
550 if (node->extends()) Visit(node->extends());
551 if (node->constructor()) Visit(node->constructor());
552 if (node->class_variable_proxy()) {
553 VisitVariableProxy(node->class_variable_proxy());
554 }
555 for (int i = 0; i < node->properties()->length(); i++) {
556 VisitLiteralProperty(node->properties()->at(i));
557 }
558 ReserveFeedbackSlots(node);
559 }
560
561
VisitObjectLiteral(ObjectLiteral * node)562 void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
563 IncrementNodeCount();
564 node->set_base_id(ReserveIdRange(node->num_ids()));
565 for (int i = 0; i < node->properties()->length(); i++) {
566 VisitLiteralProperty(node->properties()->at(i));
567 }
568 node->InitDepthAndFlags();
569 // Mark all computed expressions that are bound to a key that
570 // is shadowed by a later occurrence of the same key. For the
571 // marked expressions, no store code will be is emitted.
572 node->CalculateEmitStore(zone_);
573 ReserveFeedbackSlots(node);
574 }
575
VisitLiteralProperty(LiteralProperty * node)576 void AstNumberingVisitor::VisitLiteralProperty(LiteralProperty* node) {
577 if (node->is_computed_name())
578 DisableFullCodegenAndCrankshaft(kComputedPropertyName);
579 Visit(node->key());
580 Visit(node->value());
581 }
582
VisitArrayLiteral(ArrayLiteral * node)583 void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
584 IncrementNodeCount();
585 node->set_base_id(ReserveIdRange(node->num_ids()));
586 for (int i = 0; i < node->values()->length(); i++) {
587 Visit(node->values()->at(i));
588 }
589 node->InitDepthAndFlags();
590 ReserveFeedbackSlots(node);
591 }
592
593
VisitCall(Call * node)594 void AstNumberingVisitor::VisitCall(Call* node) {
595 if (node->is_possibly_eval()) {
596 DisableFullCodegenAndCrankshaft(kFunctionCallsEval);
597 }
598 IncrementNodeCount();
599 ReserveFeedbackSlots(node);
600 node->set_base_id(ReserveIdRange(Call::num_ids()));
601 Visit(node->expression());
602 VisitArguments(node->arguments());
603 }
604
605
VisitCallNew(CallNew * node)606 void AstNumberingVisitor::VisitCallNew(CallNew* node) {
607 IncrementNodeCount();
608 ReserveFeedbackSlots(node);
609 node->set_base_id(ReserveIdRange(CallNew::num_ids()));
610 Visit(node->expression());
611 VisitArguments(node->arguments());
612 }
613
614
VisitStatements(ZoneList<Statement * > * statements)615 void AstNumberingVisitor::VisitStatements(ZoneList<Statement*>* statements) {
616 if (statements == NULL) return;
617 for (int i = 0; i < statements->length(); i++) {
618 Visit(statements->at(i));
619 if (statements->at(i)->IsJump())
620 break;
621 }
622 }
623
VisitDeclarations(Declaration::List * decls)624 void AstNumberingVisitor::VisitDeclarations(Declaration::List* decls) {
625 for (Declaration* decl : *decls) Visit(decl);
626 }
627
628
VisitArguments(ZoneList<Expression * > * arguments)629 void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) {
630 for (int i = 0; i < arguments->length(); i++) {
631 Visit(arguments->at(i));
632 }
633 }
634
635
VisitFunctionLiteral(FunctionLiteral * node)636 void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
637 IncrementNodeCount();
638 node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids()));
639 if (node->ShouldEagerCompile()) {
640 if (eager_literals_) {
641 eager_literals_->Add(new (zone())
642 ThreadedListZoneEntry<FunctionLiteral*>(node));
643 }
644
645 // If the function literal is being eagerly compiled, recurse into the
646 // declarations and body of the function literal.
647 if (!AstNumbering::Renumber(stack_limit_, zone_, node, eager_literals_)) {
648 SetStackOverflow();
649 return;
650 }
651 }
652 ReserveFeedbackSlots(node);
653 }
654
655
VisitRewritableExpression(RewritableExpression * node)656 void AstNumberingVisitor::VisitRewritableExpression(
657 RewritableExpression* node) {
658 IncrementNodeCount();
659 node->set_base_id(ReserveIdRange(RewritableExpression::num_ids()));
660 Visit(node->expression());
661 }
662
663
Renumber(FunctionLiteral * node)664 bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
665 DeclarationScope* scope = node->scope();
666 DCHECK(!scope->HasBeenRemoved());
667
668 if (scope->new_target_var() != nullptr ||
669 scope->this_function_var() != nullptr) {
670 DisableFullCodegenAndCrankshaft(kSuperReference);
671 }
672
673 if (scope->arguments() != nullptr &&
674 !scope->arguments()->IsStackAllocated()) {
675 DisableFullCodegenAndCrankshaft(kContextAllocatedArguments);
676 }
677
678 if (scope->rest_parameter() != nullptr) {
679 DisableFullCodegenAndCrankshaft(kRestParameter);
680 }
681
682 if (IsResumableFunction(node->kind())) {
683 DisableFullCodegenAndCrankshaft(kGenerator);
684 }
685
686 if (IsClassConstructor(node->kind())) {
687 DisableFullCodegenAndCrankshaft(kClassConstructorFunction);
688 }
689
690 LanguageModeScope language_mode_scope(this, node->language_mode());
691
692 VisitDeclarations(scope->declarations());
693 VisitStatements(node->body());
694
695 node->set_ast_properties(&properties_);
696 node->set_dont_optimize_reason(dont_optimize_reason());
697 node->set_yield_count(yield_count_);
698
699 if (FLAG_trace_opt) {
700 if (disable_crankshaft_reason_ != kNoReason) {
701 // TODO(leszeks): This is a quick'n'dirty fix to allow the debug name of
702 // the function to be accessed in the below print. This DCHECK will fail
703 // if we move ast numbering off the main thread, but that won't be before
704 // we remove FCG, in which case this entire check isn't necessary anyway.
705 AllowHandleDereference allow_deref;
706 DCHECK(!node->debug_name().is_null());
707
708 PrintF("[enforcing Ignition and TurboFan for %s because: %s\n",
709 node->debug_name()->ToCString().get(),
710 GetBailoutReason(disable_crankshaft_reason_));
711 }
712 }
713
714 return !HasStackOverflow();
715 }
716
Renumber(uintptr_t stack_limit,Zone * zone,FunctionLiteral * function,Compiler::EagerInnerFunctionLiterals * eager_literals)717 bool AstNumbering::Renumber(
718 uintptr_t stack_limit, Zone* zone, FunctionLiteral* function,
719 Compiler::EagerInnerFunctionLiterals* eager_literals) {
720 DisallowHeapAllocation no_allocation;
721 DisallowHandleAllocation no_handles;
722 DisallowHandleDereference no_deref;
723
724 AstNumberingVisitor visitor(stack_limit, zone, eager_literals);
725 return visitor.Renumber(function);
726 }
727 } // namespace internal
728 } // namespace v8
729