ea25ad8bbca4722f0deeb89be9f40a1d77004757
[platform/upstream/nodejs.git] / deps / v8 / src / ast-numbering.cc
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/v8.h"
6
7 #include "src/ast.h"
8 #include "src/ast-numbering.h"
9 #include "src/compiler.h"
10 #include "src/scopes.h"
11
12 namespace v8 {
13 namespace internal {
14
15
16 class AstNumberingVisitor FINAL : public AstVisitor {
17  public:
18   explicit AstNumberingVisitor(Isolate* isolate, Zone* zone)
19       : AstVisitor(),
20         next_id_(BailoutId::FirstUsable().ToInt()),
21         dont_optimize_reason_(kNoReason) {
22     InitializeAstVisitor(isolate, zone);
23   }
24
25   bool Renumber(FunctionLiteral* node);
26
27  private:
28 // AST node visitor interface.
29 #define DEFINE_VISIT(type) virtual void Visit##type(type* node) OVERRIDE;
30   AST_NODE_LIST(DEFINE_VISIT)
31 #undef DEFINE_VISIT
32
33   bool Finish(FunctionLiteral* node);
34
35   void VisitStatements(ZoneList<Statement*>* statements) OVERRIDE;
36   void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE;
37   void VisitArguments(ZoneList<Expression*>* arguments);
38   void VisitObjectLiteralProperty(ObjectLiteralProperty* property);
39
40   int ReserveIdRange(int n) {
41     int tmp = next_id_;
42     next_id_ += n;
43     return tmp;
44   }
45
46   void IncrementNodeCount() { properties_.add_node_count(1); }
47   void DisableSelfOptimization() {
48     properties_.flags()->Add(kDontSelfOptimize);
49   }
50   void DisableOptimization(BailoutReason reason) {
51     dont_optimize_reason_ = reason;
52     DisableSelfOptimization();
53   }
54   void DisableCaching(BailoutReason reason) {
55     dont_optimize_reason_ = reason;
56     DisableSelfOptimization();
57     properties_.flags()->Add(kDontCache);
58   }
59
60   template <typename Node>
61   void ReserveFeedbackSlots(Node* node) {
62     FeedbackVectorRequirements reqs =
63         node->ComputeFeedbackRequirements(isolate());
64     if (reqs.slots() > 0) {
65       node->SetFirstFeedbackSlot(FeedbackVectorSlot(properties_.slots()));
66       properties_.increase_slots(reqs.slots());
67     }
68     if (reqs.ic_slots() > 0) {
69       int ic_slots = properties_.ic_slots();
70       node->SetFirstFeedbackICSlot(FeedbackVectorICSlot(ic_slots));
71       properties_.increase_ic_slots(reqs.ic_slots());
72       if (FLAG_vector_ics) {
73         for (int i = 0; i < reqs.ic_slots(); i++) {
74           properties_.SetKind(ic_slots + i, node->FeedbackICSlotKind(i));
75         }
76       }
77     }
78   }
79
80   BailoutReason dont_optimize_reason() const { return dont_optimize_reason_; }
81
82   int next_id_;
83   AstProperties properties_;
84   BailoutReason dont_optimize_reason_;
85
86   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
87   DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
88 };
89
90
91 void AstNumberingVisitor::VisitVariableDeclaration(VariableDeclaration* node) {
92   IncrementNodeCount();
93   VisitVariableProxy(node->proxy());
94 }
95
96
97 void AstNumberingVisitor::VisitExportDeclaration(ExportDeclaration* node) {
98   IncrementNodeCount();
99   DisableOptimization(kExportDeclaration);
100   VisitVariableProxy(node->proxy());
101 }
102
103
104 void AstNumberingVisitor::VisitModuleUrl(ModuleUrl* node) {
105   IncrementNodeCount();
106   DisableOptimization(kModuleUrl);
107 }
108
109
110 void AstNumberingVisitor::VisitEmptyStatement(EmptyStatement* node) {
111   IncrementNodeCount();
112 }
113
114
115 void AstNumberingVisitor::VisitContinueStatement(ContinueStatement* node) {
116   IncrementNodeCount();
117 }
118
119
120 void AstNumberingVisitor::VisitBreakStatement(BreakStatement* node) {
121   IncrementNodeCount();
122 }
123
124
125 void AstNumberingVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
126   IncrementNodeCount();
127   DisableOptimization(kDebuggerStatement);
128   node->set_base_id(ReserveIdRange(DebuggerStatement::num_ids()));
129 }
130
131
132 void AstNumberingVisitor::VisitNativeFunctionLiteral(
133     NativeFunctionLiteral* node) {
134   IncrementNodeCount();
135   DisableOptimization(kNativeFunctionLiteral);
136   node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
137 }
138
139
140 void AstNumberingVisitor::VisitLiteral(Literal* node) {
141   IncrementNodeCount();
142   node->set_base_id(ReserveIdRange(Literal::num_ids()));
143 }
144
145
146 void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
147   IncrementNodeCount();
148   node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
149 }
150
151
152 void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
153   IncrementNodeCount();
154   if (node->var()->IsLookupSlot()) {
155     DisableOptimization(kReferenceToAVariableWhichRequiresDynamicLookup);
156   }
157   ReserveFeedbackSlots(node);
158   node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
159 }
160
161
162 void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
163   IncrementNodeCount();
164   node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
165 }
166
167
168 void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
169   IncrementNodeCount();
170   DisableOptimization(kSuperReference);
171   ReserveFeedbackSlots(node);
172   node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
173   Visit(node->this_var());
174 }
175
176
177 void AstNumberingVisitor::VisitModuleDeclaration(ModuleDeclaration* node) {
178   IncrementNodeCount();
179   DisableOptimization(kModuleDeclaration);
180   VisitVariableProxy(node->proxy());
181   Visit(node->module());
182 }
183
184
185 void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
186   IncrementNodeCount();
187   DisableOptimization(kImportDeclaration);
188   VisitVariableProxy(node->proxy());
189   Visit(node->module());
190 }
191
192
193 void AstNumberingVisitor::VisitModulePath(ModulePath* node) {
194   IncrementNodeCount();
195   DisableOptimization(kModulePath);
196   Visit(node->module());
197 }
198
199
200 void AstNumberingVisitor::VisitModuleStatement(ModuleStatement* node) {
201   IncrementNodeCount();
202   DisableOptimization(kModuleStatement);
203   Visit(node->body());
204 }
205
206
207 void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
208   IncrementNodeCount();
209   Visit(node->expression());
210 }
211
212
213 void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
214   IncrementNodeCount();
215   Visit(node->expression());
216 }
217
218
219 void AstNumberingVisitor::VisitYield(Yield* node) {
220   IncrementNodeCount();
221   DisableOptimization(kYield);
222   ReserveFeedbackSlots(node);
223   node->set_base_id(ReserveIdRange(Yield::num_ids()));
224   Visit(node->generator_object());
225   Visit(node->expression());
226 }
227
228
229 void AstNumberingVisitor::VisitThrow(Throw* node) {
230   IncrementNodeCount();
231   node->set_base_id(ReserveIdRange(Throw::num_ids()));
232   Visit(node->exception());
233 }
234
235
236 void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
237   IncrementNodeCount();
238   node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
239   Visit(node->expression());
240 }
241
242
243 void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
244   IncrementNodeCount();
245   node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
246   Visit(node->expression());
247 }
248
249
250 void AstNumberingVisitor::VisitBlock(Block* node) {
251   IncrementNodeCount();
252   node->set_base_id(ReserveIdRange(Block::num_ids()));
253   if (node->scope() != NULL) VisitDeclarations(node->scope()->declarations());
254   VisitStatements(node->statements());
255 }
256
257
258 void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
259   IncrementNodeCount();
260   VisitVariableProxy(node->proxy());
261   VisitFunctionLiteral(node->fun());
262 }
263
264
265 void AstNumberingVisitor::VisitModuleLiteral(ModuleLiteral* node) {
266   IncrementNodeCount();
267   DisableCaching(kModuleLiteral);
268   VisitBlock(node->body());
269 }
270
271
272 void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
273   IncrementNodeCount();
274   ReserveFeedbackSlots(node);
275   if (node->is_jsruntime()) {
276     // Don't try to optimize JS runtime calls because we bailout on them.
277     DisableOptimization(kCallToAJavaScriptRuntimeFunction);
278   }
279   node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
280   VisitArguments(node->arguments());
281 }
282
283
284 void AstNumberingVisitor::VisitWithStatement(WithStatement* node) {
285   IncrementNodeCount();
286   DisableOptimization(kWithStatement);
287   node->set_base_id(ReserveIdRange(WithStatement::num_ids()));
288   Visit(node->expression());
289   Visit(node->statement());
290 }
291
292
293 void AstNumberingVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
294   IncrementNodeCount();
295   DisableSelfOptimization();
296   node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
297   Visit(node->body());
298   Visit(node->cond());
299 }
300
301
302 void AstNumberingVisitor::VisitWhileStatement(WhileStatement* node) {
303   IncrementNodeCount();
304   DisableSelfOptimization();
305   node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
306   Visit(node->cond());
307   Visit(node->body());
308 }
309
310
311 void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
312   IncrementNodeCount();
313   DisableOptimization(kTryCatchStatement);
314   Visit(node->try_block());
315   Visit(node->catch_block());
316 }
317
318
319 void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
320   IncrementNodeCount();
321   DisableOptimization(kTryFinallyStatement);
322   Visit(node->try_block());
323   Visit(node->finally_block());
324 }
325
326
327 void AstNumberingVisitor::VisitProperty(Property* node) {
328   IncrementNodeCount();
329   ReserveFeedbackSlots(node);
330   node->set_base_id(ReserveIdRange(Property::num_ids()));
331   Visit(node->key());
332   Visit(node->obj());
333 }
334
335
336 void AstNumberingVisitor::VisitAssignment(Assignment* node) {
337   IncrementNodeCount();
338   node->set_base_id(ReserveIdRange(Assignment::num_ids()));
339   if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
340   Visit(node->target());
341   Visit(node->value());
342 }
343
344
345 void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
346   IncrementNodeCount();
347   node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
348   Visit(node->left());
349   Visit(node->right());
350 }
351
352
353 void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
354   IncrementNodeCount();
355   node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
356   Visit(node->left());
357   Visit(node->right());
358 }
359
360
361 void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
362   IncrementNodeCount();
363   DisableSelfOptimization();
364   ReserveFeedbackSlots(node);
365   node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
366   Visit(node->each());
367   Visit(node->enumerable());
368   Visit(node->body());
369 }
370
371
372 void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
373   IncrementNodeCount();
374   DisableOptimization(kForOfStatement);
375   node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
376   Visit(node->assign_iterator());
377   Visit(node->next_result());
378   Visit(node->result_done());
379   Visit(node->assign_each());
380   Visit(node->body());
381 }
382
383
384 void AstNumberingVisitor::VisitConditional(Conditional* node) {
385   IncrementNodeCount();
386   node->set_base_id(ReserveIdRange(Conditional::num_ids()));
387   Visit(node->condition());
388   Visit(node->then_expression());
389   Visit(node->else_expression());
390 }
391
392
393 void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
394   IncrementNodeCount();
395   node->set_base_id(ReserveIdRange(IfStatement::num_ids()));
396   Visit(node->condition());
397   Visit(node->then_statement());
398   if (node->HasElseStatement()) {
399     Visit(node->else_statement());
400   }
401 }
402
403
404 void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
405   IncrementNodeCount();
406   node->set_base_id(ReserveIdRange(SwitchStatement::num_ids()));
407   Visit(node->tag());
408   ZoneList<CaseClause*>* cases = node->cases();
409   for (int i = 0; i < cases->length(); i++) {
410     VisitCaseClause(cases->at(i));
411   }
412 }
413
414
415 void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
416   IncrementNodeCount();
417   node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
418   if (!node->is_default()) Visit(node->label());
419   VisitStatements(node->statements());
420 }
421
422
423 void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
424   IncrementNodeCount();
425   DisableSelfOptimization();
426   node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
427   if (node->init() != NULL) Visit(node->init());
428   if (node->cond() != NULL) Visit(node->cond());
429   if (node->next() != NULL) Visit(node->next());
430   Visit(node->body());
431 }
432
433
434 void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
435   IncrementNodeCount();
436   DisableOptimization(kClassLiteral);
437   node->set_base_id(ReserveIdRange(node->num_ids()));
438   if (node->extends()) Visit(node->extends());
439   if (node->constructor()) Visit(node->constructor());
440   if (node->class_variable_proxy()) {
441     VisitVariableProxy(node->class_variable_proxy());
442   }
443   for (int i = 0; i < node->properties()->length(); i++) {
444     VisitObjectLiteralProperty(node->properties()->at(i));
445   }
446 }
447
448
449 void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
450   IncrementNodeCount();
451   node->set_base_id(ReserveIdRange(node->num_ids()));
452   for (int i = 0; i < node->properties()->length(); i++) {
453     VisitObjectLiteralProperty(node->properties()->at(i));
454   }
455 }
456
457
458 void AstNumberingVisitor::VisitObjectLiteralProperty(
459     ObjectLiteralProperty* node) {
460   if (node->is_computed_name()) DisableOptimization(kComputedPropertyName);
461   Visit(node->key());
462   Visit(node->value());
463 }
464
465
466 void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
467   IncrementNodeCount();
468   node->set_base_id(ReserveIdRange(node->num_ids()));
469   for (int i = 0; i < node->values()->length(); i++) {
470     Visit(node->values()->at(i));
471   }
472 }
473
474
475 void AstNumberingVisitor::VisitCall(Call* node) {
476   IncrementNodeCount();
477   ReserveFeedbackSlots(node);
478   node->set_base_id(ReserveIdRange(Call::num_ids()));
479   Visit(node->expression());
480   VisitArguments(node->arguments());
481 }
482
483
484 void AstNumberingVisitor::VisitCallNew(CallNew* node) {
485   IncrementNodeCount();
486   ReserveFeedbackSlots(node);
487   node->set_base_id(ReserveIdRange(CallNew::num_ids()));
488   Visit(node->expression());
489   VisitArguments(node->arguments());
490 }
491
492
493 void AstNumberingVisitor::VisitStatements(ZoneList<Statement*>* statements) {
494   if (statements == NULL) return;
495   for (int i = 0; i < statements->length(); i++) {
496     Visit(statements->at(i));
497   }
498 }
499
500
501 void AstNumberingVisitor::VisitDeclarations(
502     ZoneList<Declaration*>* declarations) {
503   for (int i = 0; i < declarations->length(); i++) {
504     Visit(declarations->at(i));
505   }
506 }
507
508
509 void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) {
510   for (int i = 0; i < arguments->length(); i++) {
511     Visit(arguments->at(i));
512   }
513 }
514
515
516 void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
517   IncrementNodeCount();
518   node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids()));
519   // We don't recurse into the declarations or body of the function literal:
520   // you have to separately Renumber() each FunctionLiteral that you compile.
521 }
522
523
524 bool AstNumberingVisitor::Finish(FunctionLiteral* node) {
525   node->set_ast_properties(&properties_);
526   node->set_dont_optimize_reason(dont_optimize_reason());
527   return !HasStackOverflow();
528 }
529
530
531 bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
532   Scope* scope = node->scope();
533
534   if (scope->HasIllegalRedeclaration()) {
535     scope->VisitIllegalRedeclaration(this);
536     DisableOptimization(kFunctionWithIllegalRedeclaration);
537     return Finish(node);
538   }
539   if (scope->calls_eval()) DisableOptimization(kFunctionCallsEval);
540   if (scope->arguments() != NULL && !scope->arguments()->IsStackAllocated()) {
541     DisableOptimization(kContextAllocatedArguments);
542   }
543
544   VisitDeclarations(scope->declarations());
545   if (scope->is_function_scope() && scope->function() != NULL) {
546     // Visit the name of the named function expression.
547     Visit(scope->function());
548   }
549   VisitStatements(node->body());
550
551   return Finish(node);
552 }
553
554
555 bool AstNumbering::Renumber(Isolate* isolate, Zone* zone,
556                             FunctionLiteral* function) {
557   AstNumberingVisitor visitor(isolate, zone);
558   return visitor.Renumber(function);
559 }
560 }
561 }  // namespace v8::internal