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